特征中两种默认实现样式之间的区别?

sea*_*lik 3 rust

有两种方法可以为Trait本身提供方法,Rustdoc通过说“提供的方法”和来区分它们impl dyn XXX。例如:

trait Trait {
    fn foo(&self) {
        println!("Default implementation");
    }
}

impl Trait {
    fn bar(&self) {
        println!("Anonymous implementation?");
    }
}
Run Code Online (Sandbox Code Playgroud)

当我阅读Rust的failure箱子的文档时,我注意到了。

他们有哪些用例?有什么区别?

Sve*_*ach 6

第一个片段,

trait Trait {
    fn foo(&self) {
        println!("Default implementation");
    }
}
Run Code Online (Sandbox Code Playgroud)

在特征上实现提供的方法。trait实现可以覆盖此方法,但是不必覆盖它。

第二个片段

impl Trait {
    fn bar(&self) {
        println!("Anonymous implementation?");
    }
}
Run Code Online (Sandbox Code Playgroud)

在类型为的特征对象上实现固有方法。只能针对特征对象(例如type)调用for的方法实现。它们不能按值接收,因为在编译时没有已知的大小,也不能在实现的具体类型(包括有界的泛型)上调用它们。dyn Traitdyn Trait&dyn Traitselfdyn TraitTraitTrait

现代的表示法是impl dyn Trait代替impl Trait,实际上,这种表示法是引入dyn关键字的激励示例之一 –旧的语法没有提供有关语义含义的任何线索,而新的语法带有dyn关键字提示实际上,此impl仅与动态调度一起使用。

特征对象是指向实现的胖指针Trait,但是对象的具体类型在编译时不一定是已知的。胖指针包含指向对象数据的指针,以及指向对象类型的虚拟方法表的指针。后者用于在运行时动态调度到正确的特征实现。

使用是相当不常见的impl dyn Trait。通常,仅当您要使用一些动态类型信息(如向下转换为实际类型)时,此选项才有用。标准库中特征对象上具有固有方法的唯一特征是AnyError


Mat*_* M. 3

简而言之:一个可以被覆盖,另一个则不能。

当您定义特征时,您定义了该特征的实现可能(或必须)覆盖的项目:

trait Trait {
    fn foo(&self) {
        println!("Default implementation");
    }
}

impl Trait for i64 {
    fn foo(&self) {
        println!("i64 implementation: {}", self);
    }
}
Run Code Online (Sandbox Code Playgroud)

另一方面,使用impl Trait,您可以定义不能被重写的固有方法:

impl Trait {
    fn bar(&self) {
        self.foo();
        self.foo()
    }
}

// Try:
impl Trait for i64 {
    fn bar(&self) { ... } // error: bar cannot be overridden.
}
Run Code Online (Sandbox Code Playgroud)

因此,固有特征方法充当模板方法模式:它们提供了一个将一个或多个可重写方法链接在一起的画布。

如果您查看failure链接的板条箱,该方法Failure::find_root_cause()会指出:

这相当于迭代iter_causes()并获取最后一项。

您可能会认为这些固有方法是便利方法,这些方法为可以手动完成的常见任务提供简单/直观的界面......但可以方便地预先定义。

注意:任何固有方法都可以作为自由函数实现,并将特征作为第一个参数;然而,自由函数不能在方法位置调用。

  • 我认为这个答案忽略了主要区别:“impl Trait”是“impl dyn Trait”的缩写,并且这些方法仅适用于_trait对象_,例如“&dyn Trait”。您不能在实现“Trait”的具体类型上调用它们。 (5认同)