在阅读别人的源码中,遇到了enum_dispatch这个Crate,那么他到底是做什么的呢?具体又怎么应用呢?在网上查找相应的资料后,大致搞清楚了它的用法 。现在我们就来学一下。
参考的文章为:https://crates.io/crates/enum_dispatch
该文章中介绍了: enum_dispatch transforms your trait objects into concrete compound types, increasing their method call speed up to 10x. 也就抛弃原来的动态调用方法,改成自动实现,实现速度提升。
示例代码为:
///enum_dispatch transforms your trait objects into concrete compound types, increasing their method call speed up to 10x.
use enum_dispatch::enum_dispatch;
// trait enum pair one
#[enum_dispatch]
enum MyBehaviorEnum {
MyImplementorA, //这里为实现了绑定tait的具体类型,而不是一个变量
MyImplementorB, //这里为实现了绑定tait的具体类型,而不是一个变量
}
#[enum_dispatch(MyBehaviorEnum)]
trait MyBehavior {
fn my_trait_method(&self);
}
// trait enum pair two
#[enum_dispatch]
trait MyBehavior2 {
fn my_trait_method2(&self);
}
#[enum_dispatch(MyBehavior2)]
enum MyBehaviorEnum2 {
MyImplementorA,
MyImplementorB,
}
pub struct MyImplementorA {
pub is_initialized: bool
}
impl MyImplementorA {
fn new() -> Self {
MyImplementorA{
is_initialized:false,
}
}
}
impl MyBehavior for MyImplementorA {
fn my_trait_method(&self) {
println!("MyImplementorA::my_trait_method::is_initialized:{}",self.is_initialized);
}
}
impl MyBehavior2 for MyImplementorA {
fn my_trait_method2(&self) {
println!("MyImplementorA::my_trait_method2::is_initialized:{}",self.is_initialized);
}
}
pub struct MyImplementorB {
pub is_initialized: bool
}
impl MyImplementorB {
fn new() -> Self {
MyImplementorB{
is_initialized:true,
}
}
}
impl MyBehavior for MyImplementorB {
fn my_trait_method(&self) {
println!("MyImplementorB::my_trait_method::is_initialized:{}",self.is_initialized);
}
}
impl MyBehavior2 for MyImplementorB {
fn my_trait_method2(&self) {
println!("MyImplementorB::my_trait_method2::is_initialized:{}",self.is_initialized);
}
}
impl MyBehaviorEnum {
fn show_info(&self) {
match self {
Self::MyImplementorA(a) => a.my_trait_method(),
Self::MyImplementorB(b) => b.my_trait_method(),
};
}
}
impl MyBehaviorEnum2 {
fn show_info2(&self) {
match self {
Self::MyImplementorA(a) => a.my_trait_method2(),
Self::MyImplementorB(b) => b.my_trait_method2(),
};
}
}
fn main() {
//测试一,注册枚举然后绑定特型,经过测试得知,具体实现可以自动转化为相应的枚举类型,并且枚举也可直接调用特型的函数,相当于实现了特型。
let a: MyBehaviorEnum = MyImplementorA::new().into();
let b: MyBehaviorEnum = MyImplementorB::new().into();
a.my_trait_method(); //no dynamic dispatch
b.my_trait_method(); //no dynamic dispatch
//测试二,先注册特型再注册枚举,此时具体用法相同
let c: MyBehaviorEnum2 = MyImplementorA::new().into();
let d: MyBehaviorEnum2 = MyImplementorB::new().into();
c.my_trait_method2(); //no dynamic dispatch
d.my_trait_method2(); //no dynamic dispatch
a.show_info();
d.show_info2();
}
//output
// MyImplementorA::my_trait_method::is_initialized:false
// MyImplementorB::my_trait_method::is_initialized:true
// MyImplementorA::my_trait_method2::is_initialized:false
// MyImplementorB::my_trait_method2::is_initialized:true
// MyImplementorA::my_trait_method::is_initialized:false
// MyImplementorB::my_trait_method2::is_initialized:true
enum_dispatch 其实是一个宏,使用它可以将枚举和对应的trait(特型)绑定在一起。与此同时,枚举的所有变量均为实现了该trait的类型。
这样 enum_dispatch 可以自动实现特型实现对象和枚举变量之间的转换。(其实本质是枚举变量绑定了一个同名类型的值,相当于一种语法糖)。
使用enum_dispatch其中一个的好处是我们只是的简单的增加枚举变量就行了(具体实现了trait类型)。