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

Iza*_*ana 6 traits rust

我阅读了这个答案,但我仍然感到困惑。

  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();
    }
    
    Run Code Online (Sandbox Code Playgroud)

    操场

    我可以理解,impl A for i32 {}因为i32是具体类型。dyn A不是具体类型(未调整大小,不能按值传递),并且您不能声明 adyn A但只能声明 a &dyn A。我应该解释吗

    // x.method_b();
    (*x).method_b();
    
    Run Code Online (Sandbox Code Playgroud)

    因为*x是dyn 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;  
    }
    
    Run Code Online (Sandbox Code Playgroud)

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

Pie*_*Pah 5

您无法声明,dyn A但可以声明,&dyn A因为dyn A是 特征对象类型,而&dyn A是指向实现 的类型实例的指针。TA

\n\n

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

\n\n
// Where B and A are traits\nimpl B for A {}\nimpl B for dyn A {}\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

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

\n\n

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

\n\n

类型的 Trait 对象dyn A必须从指针进行转换才能用作实现A. 例如,在代码示例中,i32可以转换为dyn A:

\n\n
impl B for dyn A {}\n\nimpl A for i32 {}\n\nfn main() {\n    let x: i32 = 10;\n    (&x as &dyn A).method_a(); \n    (&x as &dyn A).method_b();\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者它可以被函数强制:

\n\n
fn dispatch(a: &dyn A) {\n    a.method_b();\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

另请参阅:什么使某物成为 \xe2\x80\x9ctrait 对象\xe2\x80\x9d?

\n