【问题标题】:What does it mean to implement a trait for another trait?为另一个特征实现一个特征是什么意思?
【发布时间】:2020-06-09 13:45:50
【问题描述】:

我读过这个answer,但我仍然感到困惑。

  1. 你如何理解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

    我可以理解impl A for i32 {},因为i32 是一个具体的类型。 dyn A 不是具体类型(无大小,不能按值传递),您不能声明 dyn A 但只能声明 &dyn A。我应该解释

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

    因为*xdyn A

  2. 我也可以声明impl B for &dyn A {},那为什么我需要impl B for dyn A {}?有什么用例?

  3. 跟进:如果我修改代码

    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;  
    }
    

    它将失败并抱怨&dyn A 不是&dyn B。我知道这是一个合理的抱怨,但我为编译器提供了使用 impl B for dyn A {} 的选项。显然,编译器不认为这是一个选项。

【问题讨论】:

标签: rust traits


【解决方案1】:

你不能声明dyn A,但你可以声明&dyn A,因为dyn A是一个特征对象type,而&dyn A是一个指针实现AT 类型的实例。

从历史上看,特征可以用作类型和特征。例如,这两个都有效:

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

基本上,dyn A 只是 A 的一个糖,更清楚地表明它是用作特征对象类型的。 您不会为另一个特征实现一个特征。您为另一个特征对象类型实现一个特征

&dyn A 是一个指针实例,指向实现AT 类型的实例和一个虚拟方法表(vtable),其中包含A 的所有方法包T 实现。当 T 类型的实例稍后在运行时调用 A 的实现时,此 vtable 查找是必要的。

因此,dyn A 是一个未调整大小的类型,而 &dyn A 是一个已知大小的指针。

dyn A 类型的特征对象必须从指针转换为实现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();
}

或者它可以被一个函数强制:

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

因为 trait 是动态大小的类型 (DST),要将它们用作 trait 对象,我们必须将它们放在某种指针后面,例如 &dyn ABox<dyn A>,以便它可以指向可变大小的值并访问vtable 来调用实现的方法。

另请参阅:What makes something a “trait object”?

【讨论】:

  • 感谢您的回答。我觉得你最好解释一下(*x).method_b();。我完全同意trait object type 的解释(我会为此竖起大拇指)。但是对于impl B for dyn A {} 的解释。我发现这个users.rust-lang.org/t/… 很棒。我想和你分享。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多