文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
8.3.2 传递
特征对象(trait object)通常以指针形式出现。
A trait object is a pointer to some value that implements a given trait.
&dyn Trait // trait object Box<dyn Trait> Rc<dyn Trait> Arc<dyn Trait>
trait object +------------+ +------------+ | dptr --|----------> | data ... | +------------+ +------------+ | vptr | +----------|-+ +------------+ | | destructor | +------------> +------------+ | size | +------------+ vtable | alignment | +------------+ | method[0] | +------------+ | ... | +------------+
use std::any::Any; trait TestTrait { fn test(&self); fn as_any(&self) -> &dyn Any; } impl TestTrait for i32 { fn test(&self) { println!("{:?}", *self); } fn as_any(&self) -> &dyn Any { self } } /* ------------------------------------------*/ fn main() { let n = 123; // to trait. let x: &dyn TestTrait = &n; x.test(); // downcast. let i: &i32 = x.as_any().downcast_ref::<i32>().expect("err"); println!("{:?}", i); // box. let b = Box::new(x); b.test(); // vec. let v = vec![x]; v[0].test(); }
不能以特征变量访问目标类型成员。(不同于实现块内 Self
、 self
)
trait TestTrait { fn test(&self) { println!("test"); } } struct Data { n: i32 } impl Data { fn haha(&self) { println!("haha!"); } } impl TestTrait for Data {} /* ------------------------------------------*/ fn main() { let d = Data{ n: 100 }; d.test(); // 扩展。 d.haha(); // 方法。 assert_eq!(d.n, 100); // 字段。 let x: &dyn TestTrait = &d; x.test(); // 特征成员。 // x.haha(); // ^^^^ method not found in `&dyn TestTrait` // assert_eq!(x.n, 100); // ^ no field `n` on type `&dyn TestTrait` }
特征对象不支持关联函数调用,另须添加 Self: Sized
约束(表明编译期大小已知)。
trait TestTrait { fn new(n: i32) -> Self where Self: Sized; // !!! } struct Data { n: i32 } impl TestTrait for Data { fn new(n: i32) -> Self { Data{ n } } } /* ------------------------------------------*/ fn main() { // TestTrait::new(100); // ^^^^^^^^^^^^^^ cannot call associated function of trait let _t: &dyn TestTrait = &Data::new(100); }
作为参数和返回值传递,以及泛型(约束)版本。
trait TestTrait { fn test(&self) { println!("test"); } } impl TestTrait for i32 {} /* ------------------------------------------*/ // 动态分发。 fn test(x: &dyn TestTrait) -> &dyn TestTrait { x.test(); x } // 泛型化:静态分发,参数和返回值。 fn test2(x: impl TestTrait) -> impl TestTrait { x.test(); x } fn main() { let x = 123; let t = test(&x); // 自动将参数转换为特征对象。 t.test(); test2(x); }
fn test<T>(x: &T) -> &T where T: TestTrait{ x.test(); x } fn main() { let t = test(&123); t.test(); }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论