Mar*_*cus 3 traits rust trait-objects
在《Rust for Rustaceans》一书中,作者写道:
\n\n\n但从广义上讲,您\xe2\x80\x99 将希望在库中使用静态调度,在二进制文件中使用动态调度。在图书馆中,您希望允许用户决定哪种调度最适合他们,因为您不知道他们的需求是什么。
\n
我猜想,在二进制情况下,他指的是:
\nfn flexible_dispatch_method(_: &dyn MyTrait) {}\n\n// static dispatch\n//\nlet obj = MyType {};\nflexible_dispatch_method(&obj);\n\n// dynamic dispatch\n//\nlet trait_obj: &dyn MyTrait = &MyType {};\nflexible_dispatch_method(trait_obj);\n
Run Code Online (Sandbox Code Playgroud)\n鉴于上述情况,使用装箱对象而不是特征对象有什么优势?是不是因为需要使用生命周期:
\nfn return_new_trait_object<\'a>() -> &\'a dyn MyTrait {\n &MyType {}\n}\n
Run Code Online (Sandbox Code Playgroud)\n或者还有别的什么?根据我的理解,在动态调度情况下,无论如何,对象需要在堆中分配,所以我认为与装箱对象没有太大区别。
\nIan*_* S. 13
我认为您可能在这里误解了几件事。
dyn Trait
。这是编译器决定在编译时调用哪个函数的时候。dyn Trait
,包括Box<dyn Trait>
、&dyn Trait
、Arc<dyn Trait>
等。当您通过 a 调用函数时dyn Trait
,编译器会插入代码来查找要在运行时调用的函数,从而实现多态性和更大的灵活性。在您的代码中,flexible_dispatch_method(_: &dyn MyTrait)
始终使用动态分派,正如其参数具有类型这一事实所表明的那样&dyn MyTrait
。静态调度的一个示例如下:
fn flexible_dispatch_method<T: MyTrait + ?Sized>(_: &T) {}
Run Code Online (Sandbox Code Playgroud)
通过此声明,您的第一次使用将使用静态分派,第二次使用将使用动态分派。
动态调度更加灵活,因为它避免了到处都有泛型。这对于编写您可能想要具有多态性并轻松添加新实现的大型应用程序非常有用。然而,动态调度会带来性能成本,因此库应尽可能将调度选择权留给调用者。
至于何时使用&dyn Trait
vs Box<dyn Trait>
:这完全取决于所有权。如果您想要一个拥有的特征对象Box<dyn Trait>
,请使用,如果您想要一个借用的特征对象,请使用&dyn Trait
。
归档时间: |
|
查看次数: |
1101 次 |
最近记录: |