默认特质方法和带参数函数之间有什么区别?

6
在Rust中,当我编写带有特质的模块时,我往往会遇到设计问题。 我并不总是确定我想要什么:
pub trait Foo {
    fn foo(&self) -> bool;

    fn bar(&self) {
       if self.foo() {
           // Do something!
       } else {
           // Do something else!
       }
    }
}

或者

pub trait Foo {
    fn foo(&self) -> bool;
}

pub fn bar<T>(fooer: &T) where T: Foo {
    if fooer.foo() {
        // Do something!
    } else {
        // Do something else!
    }
}

(当然,真实的例子可能有更复杂的特征或函数签名)
虽然设计问题超出了Stack Overflow的范围,但我并不完全确定两者之间的有意义、客观差异,并且我觉得浏览标准库也没有带来太多启示。在大多数情况下,Rust的标准库似乎更喜欢使用variable.method()而不是mod::function(&variable)。然而,这仍然不能真正回答问题,因为这只是一个样式指南的争论,而不是基于对差异的客观认识。
除了明显的语法差异外,一个默认特质方法和一个模块级别的参数化函数之间的主要功能差异是什么?我有一个重要的问题:默认特质方法是否单态化以使用静态分派,还是将其作为特质对象使用self
我一开始看到的唯一区别是特质的impl可以选择覆盖默认方法实现,希望/假定提供一个履行相同契约的实现,而我保证mod::function的实现无论如何都会运行完全相同的代码(好的或坏的)。还有其他的吗?如果涉及关联类型或扩展特质,答案是否会改变?
1个回答

4

恭喜你,你已经回答了这个问题!

由于Rust只能通过trait来实现有原则的重载/覆盖,因此本质上的语义差异在于trait method可以被覆盖和自定义,而自由函数则不能。

从技术上讲,Trait::func(&self)mod::func<T: Trait>(&T)都是单态化的,而mod::func(&Trait)不是(因此会产生轻微的虚拟调用开销)。

此外,Trait::func(&self)还存在一些轻微的内存开销:虚拟表中会多出一个条目。但这可能是无法察觉的。

总之,选择通常是一个判断的过程。是否打开自定义的门户取决于你自己。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接