Rust进阶(14)-高级特征、高级函数、闭包

高级特征、高级函数、闭包

1. 高级特征

1.1 关联类型在trait定义中指定占位符类型

  1. 关联类型是一个将类型占位符与trait相关联的方式。使用type xxx定义
  2. trait的实现者会针对特定的实现在这个类型的位置指定相应的具体类型
  3. 如此可以定义几个使用多种类型的trait
  4. 如下官方迭代器泛型:
1
2
3
4
pub trait Iterator{
type Item;
fn next(&mut self) -> Option<Self::Item>;
}

使用占位符,指定一种类型 u32:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
struct Counter {
count: u32,
}

impl Counter {
fn new() -> Counter {
Counter { count: 0 }
}
}

impl Iterator for Counter {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
self.count += 1;
if self.count < 6 {
Some(self.count)
} else {
None
}
}
}

fn main() {
let mut counter = Counter::new();
for i in 0..6 {
if let Some(v) = counter.next() {
println!("i = {}, v = {}", i, v);
} else {
println!("i = {}, at end", i);
break;
}
}
}

当然也可以使用泛型,但对于其中的不同类型数据,需要强制转换,即完全限定语法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
pub trait Iterator1<T> {
fn next(&mut self) -> Option<T>;
}

struct A {
value: i32,
}

impl Iterator1<i32> for A {
fn next(&mut self) -> Option<i32> {
println!("in i32");
if self.value > 3 {
self.value += 1;
Some(self.value)
} else {
None
}
}
}

impl Iterator1<String> for A{
fn next(&mut self) -> Option<String>{
println!("in string");
if self.value >3{
self.value += 1;
Some(String::from("hello"))
}else {
None
}
}
}

fn main() {
let mut a = A{value:3};
<A as Iterator1<i32>>::next(&mut a); //完全限定语法,带上了具体的类型
<A as Iterator1<String>>::next(&mut a);
}

1.2 运算符重载和默认泛型类型参数

  1. 使用泛型类型参数时,可以为泛型指定一个默认的具体类型
  2. 运算符重载是指在特定情况下自定义运算符行为的操作
  3. Rust并不允许创建自定义运算符或者重载的运算符
  4. 不过对于std::ops中列出的运算符和相应的trait,我们可以实现运算符相关trait来重载

1.2.1 重载运算符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
use std::ops::Add;

#[derive(Debug, PartialEq)]
struct Point {
x: i32,
y: i32,
}

impl Add for Point {
type Output = Point;
fn add(self, other: Point) -> Point {
Point {
x: self.x + other.y,
y: self.y + other.y,
}
}
}

fn main() {
assert_eq!(Point { x: 1, y: 1 } + Point { x: 2, y: 2 }, Point { x: 3, y: 3 });
}

1.2.2 默认泛型类型参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
use std::ops::Add;

#[derive(Debug)]
struct Millimeters(u32);
struct Meters(u32);
impl Add<Meters> for Millimeters {
type Output = Millimeters;
fn add(self, other: Meters) -> Millimeters {
Millimeters(self.0 + other.0 * 1000)
}
}

fn main() {
let mi = Millimeters(1);
let m = Meters(1);
let r = mi + m;
println!("r = {:?}", r);
}

1.3 完全限定语法

1.3.1 完全限定语法实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
trait Animal {
fn baby_name() -> String;
}
struct Dog;
impl Dog{
fn baby_name() -> String{
String::from("Spot")
}
}

impl Animal for Dog{
fn baby_name() -> String {
String::from("puppy")
}
}

fn main() {
println!("baby_name: {}",Dog::baby_name());
println!("baby_name: {}",<Dog as Animal>::baby_name()); //完全限定语法
}

1.3.2 同名同trait方法调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
trait A{
fn print(&self);
}

trait B{
fn print(&self);
}

struct MyType;

impl A for MyType{
fn print(&self){
println!("A trait for MyType");
}
}
impl B for MyType{
fn print(&self){
println!("B trait for MyType");
}
}
impl MyType{
fn print(&self){
println!("MyType");
}
}

fn main() {
let my_type = MyType;
my_type.print();
//等价
MyType::print(&my_type);

A::print(&my_type);
B::print(&my_type);
}

1.4 父trait

  1. 用于在另一个trait中使用某trait的功能
  2. 有时候我们可能会需要某个trait使用另一个trait的功能
  3. 在这种情况下,需要能够依赖相关的trait也被实现
  4. 这个所需的trait是我们实现的trait的父(超)trait(supertrait)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
use std::fmt;

trait OutPrint: fmt::Display {
//要求实现Display trait
fn out_print(&self) {
let output = self.to_string();
println!("output: {}", output);
}
}

struct Point {
x: i32,
y: i32,
}

impl OutPrint for Point {}

impl fmt::Display for Point {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({},{})", self.x, self.y)
}
}

fn main() {
println!("Hello, world!");
}

1.5 nettype模式用以在外部类型上实现外部trait

  1. 孤儿规则(orphan rule):只要trait或类型对于当前crate是本地的话就可以在此类型上实现该trait.
  2. 一个绕开这个限制的方法是使用newtype模式(newtype pattern)
  3. 即使用Wrapper关键词
1
2
3
4
5
6
7
8
9
10
11
12
use std::fmt;
struct Wrapper(Vec<String>);

impl fmt::Display for Wrapper{
fn fmt(&self,f:&mut fmt::Formatter)->fmt::Result{
write!(f,"({})",self.0.join(","))
}
}
fn main() {
let w = Wrapper(vec![String::from("hello"),String::from("world")]);
println!("w = {}",w);
}

1.6 类型别名

类型别名的主要用途是减少重复

1
2
3
4
5
6
7
8
type Kilometers = i32;

fn main() {
let x: i32 = 5;
let y: Kilometers = 6;
let r: i32 = x + y;
println!("x +y = {}", r);
}

1.7 从不返回的never type

Rust有一个叫做!的特殊类型,在类型理论术语中,它被称为empty type,因为它没有值。我们更倾向于称为nerver type。在函数不返回的时候充当返回值。

2. 高级函数和闭包

  1. 函数指针允许我们使用函数作为另一个函数的参数
  2. 函数的类型是fn,fn 被称为函数指针。指定参数为函数指针的语法类似于闭包
  3. 函数指针实现了Fn、FnMut、FnOnce

2.1 函数指针和闭包的基本使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
fn add_one(x: i32) -> i32 {
x + 1
}

fn do_twice(f: fn(i32) -> i32, val: i32) -> i32 {
f(val) + f(val)
}

fn wapper_func<T>(t: T, v: i32) -> i32 where T: Fn(i32) -> i32 {
t(v)
}

fn func(v: i32) -> i32 {
v + 1
}

fn main() {
let r = do_twice(add_one, 5);
println!("r = {}", r);

let a = wapper_func(|x| x + 1, 1);
println!("a = {}", a);
let b = wapper_func(func, 1);
println!("b = {}", b);
}

2.2 函数指针返回闭包

1
2
3
4
5
6
7
8
9
10

fn return_clo() ->Box<dyn Fn(i32)->i32>{
Box::new(|x| x+1)
}

fn main() {
let c = return_clo();
println!("1 + 1 = {}",c(1));
println!("1 + 1 = {}",(*c)(1)); //解引用多态
}

总结

本文编辑完毕

参考

[1] Rust 程序设计语言

  • Copyrights © 2017-2023 Jason
  • Visitors: | Views:

谢谢打赏~

微信