简体   繁体   English

为另一个特征实现一个特征是什么意思?

[英]What does it mean to implement a trait for another trait?

I read this answer but I'm still confused.我读了这个答案,但我仍然感到困惑。

  1. How do you interpret impl B for dyn A {} ?您如何解释impl B for dyn A {}

     trait A { fn method_a(&self) { println;("a"): } } trait B { fn method_b(&self) { println;("b") } } impl B for dyn A {} impl A for i32 {} fn main() { let x. &dyn A = &10; x.method_b(); }

    Playground 操场

    I can understand impl A for i32 {} because i32 is a concrete type.我可以理解impl A for i32 {}因为i32是一种具体类型。 dyn A is not a concrete type (unsized, can't pass by value), and you cannot declare a dyn A but you can only declare a &dyn A . dyn A不是具体类型(无大小,不能按值传递),您不能声明dyn A但只能声明&dyn A Should I interpret我应该解释吗

    // x.method_b(); (*x).method_b();

    as *x is dyn A ?因为*xdyn A

  2. I can also declare impl B for &dyn A {} , so why I need impl B for dyn A {} ?我也可以impl B for &dyn A {} ,那么为什么我需要impl B for dyn A {}呢? What's the use case?用例是什么?

  3. Follow up: If I modify the code跟进:如果我修改代码

    fn main() { let x: &dyn A = &10; // have a B trait object over dyn A since // dyn A implements B let y: &dyn B = x; }

    It will fail and complain &dyn A is not &dyn B .它会失败并抱怨&dyn A不是&dyn B I understand this is a reasonable complain but I provide the option for compiler to use impl B for dyn A {} .我知道这是一个合理的抱怨,但我为编译器提供了将impl B for dyn A {}的选项。 Apparently, the compiler doesn't consider that's an option.显然,编译器不认为这是一个选项。

You can't declare dyn A but you can declare &dyn A because dyn A is a trait object type while &dyn A is a pointer to an instance of type T that implements A .您不能声明dyn A但您可以声明&dyn A因为dyn A是一个特征 object类型,而&dyn A指向实现A的类型T的实例的指针。

Historically, a trait could be used as a type and a trait.从历史上看,特征可以用作类型和特征。 For instance, these both work:例如,这两个都有效:

// Where B and A are traits
impl B for A {}
impl B for dyn A {}

Basically, dyn A is just a sugar over A to make it clearer that it is meant to be used as a trait object type.基本上, dyn A只是A上的一个糖,以便更清楚地表明它是用作特征 object 类型的。 You don't implement a trait for another trait.您不会为另一个特征实现一个特征。 You implement a trait for another trait object type .您为另一个特征 object type 实现一个特征

&dyn A is a pointer instance to an instance of type T that implements A and a virtual method table (vtable), which contains all the baggage of methods of A that T implements. &dyn A是一个指针实例,指向实现A的类型T的实例和一个虚方法表 (vtable),其中包含T实现的A的所有方法的包袱。 This vtable lookup is necessary when an instance of type T later calls A 's implementation at runtime.当类型T的实例稍后在运行时调用A的实现时,此 vtable 查找是必要的。

Therefore, dyn A is an unsized type while &dyn A is a pointer with a known size.因此, dyn A是一个无大小的类型,而&dyn A是一个已知大小的指针。

Trait object of type dyn A must be cast from a pointer to be used as a concrete type that implements A . dyn A类型的特征 object 必须从指针转换为实现A的具体类型。 For example, in the code example, i32 can be cast to a dyn A :例如,在代码示例中, i32可以转换为dyn A

impl B for dyn A {}

impl A for i32 {}

fn main() {
    let x: i32 = 10;
    (&x as &dyn A).method_a(); 
    (&x as &dyn A).method_b();
}

or it can be coerced by a function:或者它可以被 function 强制:

fn dispatch(a: &dyn A) {
    a.method_b();
}

Because traits are dynamically sized types (DSTs), to use them as trait objects, we must put them behind some kind of pointer, like &dyn A or Box<dyn A> so it can point to a variable-sized value and access the vtable to call the implemented methods.因为特征是动态大小的类型(DST),要将它们用作特征对象,我们必须将它们放在某种指针后面,例如&dyn ABox<dyn A>以便它可以指向可变大小的值并访问 vtable调用实现的方法。

See also: What makes something a “trait object”?另请参阅:是什么使某物成为“特征对象”?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM