Rust Trait
Rust trait
Rust中的trait类似于其他语言的接口类型
一般定义如下:
1 | trait A { |
常见的两张分发形式
- 静态分发
1
2
3
4
5
6
7fn test(a: impl A) -> i32 {
a.a()
}
// 等价于 =>
fn test<T: A>(a: T) -> i32 {
a.a()
}静态分发没有性能损耗,会在编译期间进行单态化,在栈上分配,就像是这样:
1 | struct C; |
- 动态分发
1
2
3fn test(a: &dyn A) -> i32 {
a.a()
}动态分发有性能损耗,实在运行时才确定,有延迟绑定的效果,灵活性高,在堆上分配,原有类型会被抹去,创建一个trait object,并为其分配满足该trait的vtable


在参数中使用trait object
在参数中使用trait object比较简单,就像这样:
1 | trait CookieStore: Send + Sync { // : Send + Sync表示实现CookieStore trait时也要满足Send和Sync trait,类似于继承 |
在函数返回值中使用trait object
这是trait object使用频率比较高的场景
1 | trait Storage: Send + Sync + 'static { |
async trait的例子
rust目前并不支持trait中使用async fn,但可以使用async_trait宏来解决
1 |
|
实际上就是使用了trait object作为返回值,这样就可以不管fetch()的实现和Future的类型,都可以被 trait object 统一起来,调用者只需要按照正常 Future 的接口使用即可.
在数据结构中使用trait object
1 | struct State { |
这是我们大部分时候处理这样的数据结构的选择。但是,过多的泛型参数会带来两个问题:首先,代码实现过程中,所有涉及的接口都变得非常臃肿,你在使用 HandshakeState<R, D, K> 的任何地方,都必须带着这几个泛型参数以及它们的约束。其次,这些参数所有被使用到的情况,组合起来,会生成大量的代码。而使用 trait object,我们在牺牲一点性能的前提下,消除了这些泛型参数,实现的代码更干净清爽,且代码只会有一份实现。
闭包
1 | struct AttributeGetter( |