< 返回版块

hzqd 发表于 2024-07-23 15:28

Rust 允许开发者编写如下代码:

trait A {}
trait B {}
impl A for dyn B {}

但我不知道该语言特性有什么用处,大家有没有小例子或者实际场景的使用案例呢?

评论区

写评论
fakeshadow 2024-07-25 01:47

常见的用处是防止trait方法的默认实现被覆盖,例如:

pub trait Foo {
    fn foo(&self) {}
}

impl dyn Foo {
    fn foo_private(&self) {
       println!("私有默认实现无法被覆盖");
    }
}

struct Bar;

impl Foo for Bar {
    fn foo(&self) {
        println!("公有默认实现可以被覆盖")
    }

    // 以下无法编译
    // fn foo_private(&self) { }
}

fn main() {
    let bar = Bar;
    bar.foo();
    (&bar as &dyn Foo).foo_private();
}

除了上面兄弟提到的std::any::Any,std::error::Error也是利用这个方法来避免一些方法被覆盖

lithbitren 2024-07-24 10:08

感觉就是种方便的方法继承,存在trait A, B,在声明了impl A for dyn B {}以后,声明struct C和实现impl B for C {}后,struct C不用声明和A的关系(比如impl A for C {}),就可以通过c: &dyn B的类型来调用A的方法。

使用上,impl A for dyn B {}一定程度上和impl <T: B + ?Sized> A for T {}类似。

如果c: C这样的静态分发的变量,声明impl<T: B> A for T {}也可以让struct C调用trait A的方法。

当然,一般来说动态定义的使用范围更大一些,可以把不同的结构体(实现了B的其他结构体D, E, F)通过定义成&dyn B类型来装进一个数组或容器里面。不过这种dyn写法似乎是不支持祖父方法继承,泛型法支持持续的联级继承(尽管一般来说不推荐在rust里搞复杂的继承机制)。

mod lib {
    pub trait A {
        fn a(&self) {
            println!("Calling from trait A");
        }
    }
    
    pub trait B {
        fn b(&self) {
            println!("Calling from trait B");
        }
    }
    
    // 适用于let c = C;的静态定义
    // impl<T: B> A for T {
    //     fn a(&self) {
    //         println!("Calling from impl <T: B> A for T");
    //     }
    // }
    
    // 适用于let c: &dyn B = &C;动态定义
    // impl<T: B + ?Sized> A for T {
    //     fn a(&self) {
    //         println!("Calling from impl <T: B + ?Sized> A for T");
    //     }
    // }
    
    // 适用于let c: &dyn B = &C;动态定义
    impl A for dyn B {
        fn a(&self) {
            println!("Calling from impl A for dyn B");
        }
    }
}

// 以上定义可能是模块代码,以下是具体的业务代码

use lib::{ A, B };

struct C;

impl B for C {}

fn main() {
    // let c = C;
    let c: &dyn B = &C;
    c.a();
    c.b();
}
TinusgragLin 2024-07-23 17:57

收获今日“em,还能这样?!”时刻,确实不大常看到,不过 Github 上能搜到大约 7k 个结果

liusen-adalab 2024-07-23 16:50

标准库的 Any: https://doc.rust-lang.org/src/core/any.rs.html#151

1 共 4 条评论, 1 页