什么" dyn"是什么意思?

时间:2018-06-01 19:39:13

标签: syntax rust

我最近看到使用dyn关键字的代码:

fn foo(arg: &dyn Display) {}

fn bar() -> Box<dyn Display> {}

这种语法是什么意思?

3 个答案:

答案 0 :(得分:21)

TL; DR:用于指定特征对象的类型的语法,出于清晰的原因应该是首选。

自Rust 1.0以来,特质已经过了双重生活。一旦声明了特征,它就可以用作特征或类型:

// As a trait
impl MyTrait for SomeType {}

// As a type!
impl MyTrait {}
impl AnotherTrait for MyTrait {}

你可以想象,这种双重含义会引起一些混乱。此外,由于MyTrait类型是未分级/动态大小的类型,因此可能会使人们看到非常复杂的错误消息。

为了改善此问题,RFC 2113引入了dyn语法。从Rust 1.27开始提供此语法:

use std::{fmt::Display, sync::Arc};

fn main() {
    let display_ref: &dyn Display = &42;
    let display_box: Box<dyn Display> = Box::new(42);
    let display_arc: Arc<dyn Display> = Arc::new(42);
}

这个新关键字与impl Trait语法相似,并努力使trait object的类型明显区别于&#34;裸&#34;特质语法。

可能在随后的edition of Rust中,不推荐使用裸语法,然后最终删除。

答案 1 :(得分:0)

dyn 关键字用于指示类型是特征对象。根据{{​​3}}:

<块引用>

trait 对象是另一种类型的不透明值,它实现了 一组特征。

换句话说,我们在编译时并不知道对象的具体类型,我们只知道对象实现了 trait。

因为 trait 对象的大小在编译时是未知的,所以它们必须放在指针后面。例如,如果 Trait 是您的特征名称,那么您可以按以下方式使用特征对象:

  • Box<dyn Trait>
  • &dyn Trait
  • 和其他指针类型

保存 trait 对象的变量/参数是胖指针,由以下组件组成:

  • 指向内存中对象的指针
  • 指向该对象的虚表的指针,虚表是一个带有指向实际方法实现的指针的表。

有关详细信息,请参阅我在 the Rust docs 上的回答。

答案 2 :(得分:0)

我发现这篇博文非常清楚地解释了这个功能:https://medium.com/digitalfrontiers/rust-dynamic-dispatching-deep-dive-236a5896e49b

相关摘录:

struct Service<T:Backend>{
    backend: Vec<T>  // Either Vec<TypeA> or Vec<TypeB>, not both
}
...
let mut backends = Vec::new();
backends.push(TypeA);
backends.push(TypeB);  // <---- Type error here

对比

struct Service{
    backends: Vec<Box<dyn Backend>>
}
...
let mut backends = Vec::new();
backends.push( Box::new(PositiveBackend{}) as Box<dyn Backend>);
backends.push( Box::new(NegativeBackend{}) as Box<dyn Backend>);