0°

Rust语言开发基础(八)Rust的接口及其实现

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

trait(特征)类似于其他语言中的interface或者protocol,指定一个实际类型必须满足的功能集合

一、如何理解trait,可以从我们所了解的接口特性去推断trait的用法

  1. 那么作为一个类接口的关键字,意味着被它修饰的类不包含实现的方法fn,只定义函数名称和参数,由这个类的实现类去完成它的方法。
  2. 任何实现接口的类都必须去实现接口的方法,这种特性恰好可以作为一种从上到下的约束,应用到Rust语法里面。
  3. 接口也可以不断被继承,最后实现类须要实现所有的接口里的方法。

 

二、trai的实现方式

  1. 定义接口

trait HasArea {
fn area(&self) ->f64;
}

 

  1. 实现接口

为一个结构体圆增加一个计算圆面积的函数:

struct Circle {
x:f64,
y:f64,
radius:f64,
}

impl HasAreaforCircle {
fn area(&self) ->f64 {
std::f64::consts::PI* (self.radius *self.radius)
}
}


fn main() {
let c =Circle {
x:0.0f64,
y:0.0f64,
radius:1.0f64,
};
println!("circle c has an area of {}", c.area());
}

最终输出:
circle c has an area of 1

  1. 继承接口

trait Foo {
fn foo(&self);
}

trait FooBar:Foo {
fn foobar(&self);
}
实现:
struct Baz;

impl FooforBaz {
fnfoo(&self) { println!("foo"); }
}

impl FooBarforBaz {
fn foobar(&self) { println!("foobar"); }
}

 

4.自动化实现接口

Rust会自动帮你实现接口,当然必须是某些特定的接口方法,就好像利用开发工具帮你实现一些接口方法一样。
能帮你实现的方法仅限于:Clone,Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd
这些方法一般是常见的方法,要自动实现上述方法,前提是使用derive属性。

#[derive(Debug)]structFoo;

fn main() {
println!("{:?}",Foo);
}

5.自带默认方法

tait修饰的类都自动被系统加上一个默认方法,这个默认方法不要求被实现类实现,当然实现类可以去实现它并覆盖原有方法。

trait Foo {
fn is_valid(&self) ->bool;

    fn is_invalid(&self) ->bool { !self.is_valid() }
}
is_invalid是默认方法,Foo的实现者并不要求实现它,如果选择实现它,会覆盖掉它的默认行为。

 

三、Rust里面的应用场景

1.给泛型增加约束,或者说给泛型增加实现要求。

例如:Debug是Rust内置的一个trait,为"{:?}"实现打印内容,函数foo接受一个泛型作为参数,并且约定其需要实现Debug
use std::fmt::Debug;

fn foo<T:Debug>(s:T) {
println!("{:?}", s);
}

2.给泛型增加多个trait,也即所谓的多重约束。

use std::fmt::Debug;

fn foo<T:Debug+Clone>(s:T) {
s.clone();
println!("{:?}", s);
}
<T: Debug + Clone>中Debug和Clone使用+连接,表示泛型T需要同时实现这两个trait。

 

  1. where关键字其实只是为多重约束增加一些写法。

标准写法:
use std::fmt::Debug;

fn foo<T:Clone,K:Clone+Debug>(x:T, y:K) {
x.clone();
y.clone();
println!("{:?}", y);
}
where从句写法一:
fn foo<T,K>(x:T, y:K) whereT:Clone,K:Clone+Debug {
x.clone();
y.clone();
println!("{:?}", y);
}
where从句写法二:
fn foo<T,K>(x:T, y:K)
whereT:Clone,K:Clone+Debug {
x.clone();
y.clone();
println!("{:?}", y);
}
语法糖,这只是语法糖!

 

4.孤僻的应用场景,给内置类型增加trait

trait HasArea {
fn area(&self) ->f64;
}

impl HasAreafori32 {
fn area(&self) ->f64 {
*selfasf64
}
}

area();

最后的输出接口f64类型的数值,这个方法相当有用

**注意:
**

  1. 当你为某类型实现某 trait 的时候,必须要求类型或者 trait 至少有一个是在当前 crate 类库中定义的。你不能为第三方的类型实现第三方的 trait 。
  2. 在调用 trait 中定义的方法的时候,一定要记得让这个 trait 可被访问。

 

参考:https://github.com/rustcc/RustPrimer/blob/master/10-trait/10-00-overview.md

 

 

 

 

 

转载于:https://my.oschina.net/pagecorrect/blog/655924

「点点赞赏,手留余香」

    还没有人赞赏,快来当第一个赞赏的人吧!