fnprint_number(n: Number){matchn{Number{odd: true,value}=>println!("Odd number: {}",value),Number{odd: false,value}=>println!("Even number: {}",value),}}// this prints the same as before
match必须是详尽的,至少需要一个分支来进行匹配
12345678
fnprint_number(n: Number){matchn{Number{value: 1,..}=>println!("One"),Number{value: 2,..}=>println!("Two"),Number{value,..}=>println!("{}",value),// if that last arm didn't exist, we would get a compile-time error}}
fnmain(){letmutn=Number{odd: true,value: 17,}n.value=19;// all good}
trait是多种类型拥有的共同点:
123
traitSigned{fnis_strictly_negative(self)-> bool;}
您可以实现:
为任意类型实现你自己定义的trait
为你的类型实现任意类型的trait
不允许为别人的类型实现别人的trait
这些被称为“孤立规则”(orphan rules)。
下面是自定义trait在自定义类型上的实现:
1 2 3 4 5 6 7 8 910
implSignedforNumber{fnis_strictly_negative(self)-> bool{self.value<0}}fnmain(){letn=Number{odd: false,value: -44};println!("{}",n.is_strictly_negative());// prints "true"}
我们在外部类型(甚至是基本类型)上的实现的自定义trait:
1 2 3 4 5 6 7 8 910
implSignedfori32{fnis_strictly_negative(self)-> bool{self<0}}fnmain(){letn: i32=-44;println!("{}",n.is_strictly_negative());// prints "true"}
自定义类型的外部trait:
1 2 3 4 5 6 7 8 9101112131415161718
// `Neg` 特性用于重载 `-`,// 一元减运算符。implstd::ops::NegforNumber{typeOutput=Number;fnneg(self)-> Number{Number{value: -self.value,odd: self.odd,}}}fnmain(){letn=Number{odd: true,value: 987};letm=-n;// this is only possible because we implemented `Neg`println!("{}",m.value);// prints "-987"}
fnmain(){leta: i32=15;letb=a;// `a` is copiedletc=a;// `a` is copied again}
这也是正常的:
123456789
fnprint_i32(x: i32){println!("x = {}",x);}fnmain(){leta: i32=15;print_i32(a);// `a` is copiedprint_i32(a);// `a` is copied again}
但Number类型没有实现Copy,所以下面的代码不起作用:
12345
fnmain(){letn=Number{odd: true,value: 51};letm=n;// `n` is moved into `m`leto=n;// error: use of moved value: `n`}
这也不行:
123456789
fnprint_number(n: Number){println!("{} number {}",ifn.odd{"odd"}else{"even"},n.value);}fnmain(){letn=Number{odd: true,value: 51};print_number(n);// `n` is movedprint_number(n);// error: use of moved value: `n`}
但如果采用不可变的引用print_number,就是可行的:
123456789
fnprint_number(n: &Number){println!("{} number {}",ifn.odd{"odd"}else{"even"},n.value);}fnmain(){letn=Number{odd: true,value: 51};print_number(&n);// `n` is borrowed for the time of the callprint_number(&n);// `n` is borrowed again}
如果变量被声明为可变的,则函数参数使用可变引用也可以工作:
1 2 3 4 5 6 7 8 910111213
fninvert(n: &mutNumber){n.value=-n.value;}fnprint_number(n: &Number){println!("{} number {}",ifn.odd{"odd"}else{"even"},n.value);}fnmain(){// this time, `n` is mutableletmutn=Number{odd: true,value: 51};print_number(&n);invert(&mutn);// `n is borrowed mutably - everything is explicitprint_number(&n);}
// note: `Copy` requires that `Clone` is implemented tooimplstd::clone::CloneforNumber{fnclone(&self)-> Self{Self{..*self}}}implstd::marker::CopyforNumber{}
structPair<T>{a: T,b: T,}fnprint_type_name<T>(_val: &T){println!("{}",std::any::type_name::<T>());}fnmain(){letp1=Pair{a: 3,b: 9};letp2=Pair{a: true,b: false};print_type_name(&p1);// prints "Pair<i32>"print_type_name(&p2);// prints "Pair<bool>"}
标准库中的类型Vec(即分配在堆上的数组)就是泛型实现的:
12345678
fnmain(){letmutv1=Vec::new();v1.push(1);letmutv2=Vec::new();v2.push(false);print_type_name(&v1);// prints "Vec<i32>"print_type_name(&v2);// prints "Vec<bool>"}
fnmain(){leto1: Option<i32>=Some(128);o1.unwrap();// this is fineleto2: Option<i32>=None;o2.unwrap();// this panics!}// output: thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/libcore/option.rs:378:21
enumOption<T>{None,Some(T),}impl<T>Option<T>{fnunwrap(self)-> T{// enums variants can be used in patterns:matchself{Self::Some(t)=>t,Self::None=>panic!(".unwrap() called on a None option"),}}}useself::Option::{None,Some};fnmain(){leto1: Option<i32>=Some(128);o1.unwrap();// this is fineleto2: Option<i32>=None;o2.unwrap();// this panics!}// output: thread 'main' panicked at '.unwrap() called on a None option', src/main.rs:11:27
fnmain(){letmutx=42;letx_ref=&x;x=13;println!("x_ref = {}",x_ref);// error: cannot assign to `x` because it is borrowed}
当不可变地借用时,不能同时可变地的借用:
Tip
即不能对一个变量同时创建不可变和可变的引用
1234567
fnmain(){letmutx=42;letx_ref1=&x;letx_ref2=&mutx;// error: cannot borrow `x` as mutable because it is also borrowed as immutableprintln!("x_ref1 = {}",x_ref1);}
函数参数中的引用同样存在生命周期:
1234
fnprint(x: &i32){// `x` is borrowed (from the outside) for the// entire time this function is called.}