前面说过,trait object 允许一个值有不同的类型,只要这个类型实现了特定的 trait。有无数种可能性,...
let obj = return_trait_object(); obj.do_something(); } 在上面的代码中,我们定义了一个特征MyTrait和一个结构体MyStruct,并为MyStruct实现了MyTrait。然后,我们定义了一个函数return_trait_object,它返回一个Box<dyn MyTrait>,即一个特征对象的盒子。在main函数中,我们调用return_trait_object并...
Pointers to trait objects also store a pointer to a vtable. 这里引出了两个重要的概念,胖指针(fat pointer),即DST的指针的大小是普通指针的两倍,对slice来说,一个指针存地址,另一个指针存slice的长度;对trait object来说,一个指针存地址,另一个指针存虚表(vtable)。 看起来我们终于接触到了动态类型系统的...
impl Trait:静态分发 dyn Trait:动态分发 静态分发:在编译期就确定了具体返回类型,函数只能返回一种类型。 动态分发:在运行时才能确定具体返回类型,函数可以返回多种类型。 Trait Object:指向trait的指针,假设Animal是一个triait,那么&Animal和Box<Animal>都是一种Trait Object。 胖指针:用于指代动态大小类型(DST)的...
Box<dyn Error> 类型是一个trait 对象(trait object)第16节 顾及不同类型值的 trait 对象”:https://kaisery.github.io/trpl-zh-cn/ch17-02-trait-objects.html#顾及不同类型值的-trait-对象部分会做介绍。目前可以将 Box<dyn Error> 理解为 “任何类型的错误”。在返回 Box<dyn Error> 错误类型 main 函...
impl_downcast!(MyTrait); 之后使用就可以很简单地调用downcast来实现向下转换了: ifletSome(my_impl)=my_trait_object.downcast::<MyImpl>(){// ...逻辑} 补充:想起来这个方法还有一个优势,就是可以让编译器检查转换的类型是否为实现了该trait类型。
A trait object is an opaque value of another type that implements a set of traits. The set of traits is made up of an object safe base trait plus any number of auto traits. 比较重要的一点是 trait object 属于 Dynamically Sized Types(DST),在编译期无法确定大小,只能通过指针来间接访问,常见的...
error[E0746]:returntype cannot have an unboxed trait object--> src/main.rs:144:24 | 144 | fn return_closure() -> Fn(i32) ->i32 {| ^^^ doesn't have a size known at compile-time 错误又一次指向了Sized trait! Rust并不知道需要多少空间来储存闭包。不过我们在之前了解到这种情况的解决方法...
Object safety 总结 参考 在Rust 设计目标中,零成本抽象是非常重要的一条,它让 Rust 具备高级语言表达能力的同时,又不会带来性能损耗。零成本的基石是泛型与 trait,它们可以在编译期把高级语法编译成与高效的底层代码,从而实现运行时的高效。这篇文章就来介绍 trait,包括使用方式与三个常见问题的分析,在问题探究的...
Trait 对象是动态分发,它在运行时根据对象的实际类型调用方法;而泛型是静态分发,它在编译时就确定了调用的方法。 Trait 对象可以包含不同类型的对象,因为它们的大小是相同的(由指针大小决定);而泛型必须在编译时确定类型,因此要求所有对象的类型都相同。