trait
Rust的trait与Scala的trait类似(可以理解为Java的interface,但也不能全这么理解)。trait可以翻译为特征。
定义trait
trait Math {
fn squares_sum(&self) -> f64;
}
&self
表示的是函数的调用者的不可变引用。类似Python中的self或Javascript中的this。
只不过Rust中,&self必须在函数参数中显示声明。
为类型实现trait
trait只是定义了函数,并没有实现函数。实现代码交给具体实现它的类型去补充。
基本语法格式:
impl my_trait for my_struct {
// 实现trait的方法。
}
例:为 struct Point 实现 Math trait。
struct Point {
x:i32,
y:i32
}
trait Math {
fn squares_sum(&self) -> f64;
}
impl Math for Point {
fn squares_sum(&self) -> f64 {
(self.x*self.x + self.y*self.y) as f64
}
}
使用上面定义的Circle,调用方法:
fn main() {
let p = Point {x:10,y:20};
println!("{}",p.squares_sum());
}
为基础类型实现trait
// 省略上面定义的部分。
impl Math for i32 {
fn squares_sum(&self) -> f64 {
( *self * *self) as f64
}
}
fn main() {
let res = 10.squares_sum();
println!("{}",res);
}
trait的默认方法
与Scala类似,trait可以有默认方法。
trait Foo {
fn is_valid(&self) -> bool;
fn is_invalid(&self) -> bool {
!self.is_valid()
}
}
在实现trait的代码中,可以重新实现trait的默认方法,也可以不实现默认方法。
trait的继承
使用:
表示trait的继承关系。
trait A : B { // A继承B。
// ...
}
例:FooBar继承Foo。FooBar扩展了Foo的内容。
trait Foo {
fn foo(&self);
}
trait FooBar : Foo {
fn foobar(&self);
}
FooBar的实现者也要同时实现Foo:
struct Baz;
impl Foo for Baz {
fn foo(&self) { println!("foo"); }
}
impl FooBar for Baz {
fn foobar(&self) { println!("foobar"); }
}
自动实现特殊方法 derive属性
Rust提供了一个属性derive来自动实现一些trait,能被derive使用的trait包括:
- Clone
- Copy
- Debug
- Default
- Eq
- Hash
- Ord
- PartialEq
- PartialOrd
例:Foo自动实现Debug trait。
#[derive(Debug)]
struct Foo;
fn main() {
println!("{:?}", Foo);
}
Drop trait
Drop trait是Rust提供的一个非常特殊的trait。
Drop trait中有一个drop(&mut self)
方法。若一个变量的类型实现了Drop trait,则在这种变量离开作用域后,会自动调用drop方法。
这有点类似于C++的析构函数。
需要注意两点:
- Drop trait 无法为基础类型实现方法。
- 多个变量离开作用域,drop方法调用顺序与变量声明顺序相反。(这与Go的defer语句类似。原因很简单,方法调用结束,变量出栈,先入后出。)
struct Point {
x:i32,
y:i32
}
impl Drop for Point {
fn drop(&mut self) {
println!("({:?},{:?}) has drop",(*self).x,(*self).y);
}
}
fn main() {
let p1 = Point {x:10,y:10};
println!("point1 is ({},{})",p1.x,p1.y);
let p2 = Point {x:20,y:20};
println!("point2 is ({},{})",p2.x,p2.y);
}
打印输出:
point1 is (10,10)
point2 is (20,20)
(20,20) has drop
(10,10) has drop