在为引用和非引用类型实现一个特征时,我是否必须实现两次



我想为引用和非引用类型实现一个特征。我是否必须实现两次函数,或者这不是惯用语?

下面是演示代码:

struct Bar {}
trait Foo {
    fn hi(&self);
}
impl<'a> Foo for &'a Bar {
    fn hi(&self) {
        print!("hi")
    }
}
impl Foo for Bar {
    fn hi(&self) {
        print!("hi")
    }
}
fn main() {
    let bar = Bar {};
    (&bar).hi();
    &bar.hi();
}
这是

Borrow特征的一个很好的例子。

use std::borrow::Borrow;
struct Bar;
trait Foo {
    fn hi(&self);
}
impl<B: Borrow<Bar>> Foo for B {
    fn hi(&self) {
        print!("hi")
    }
}
fn main() {
    let bar = Bar;
    (&bar).hi();
    &bar.hi();
}

不,您不必复制代码。相反,您可以委派:

impl Foo for &'_ Bar {
    fn hi(&self) {
        (**self).hi()
    }
}

我会更进一步,为实现该特征的类型的所有引用实现该特征:

impl<T: Foo> Foo for &'_ T {
    fn hi(&self) {
        (**self).hi()
    }
}

另请参阅:

  • 我什么时候不应该实现一个特征来引用该特征的实现者?
  • 为引用类型
  • 和非引用类型实现特征会导致实现冲突

&bar.hi();

此代码等效于 &(bar.hi()),可能不是您想要的。

另请参阅:

  • 为什么借临时是合法的?
您可以使用

Cow

use std::borrow::Cow;
#[derive(Clone)]
struct Bar;
trait Foo {
    fn hi(self) -> &'static str;
}
impl<'a, B> Foo for B where B: Into<Cow<'a, Bar>> {
    fn hi(self) -> &'static str {
        let bar = self.into();
        // bar is either owned or borrowed:
        match bar {
            Cow::Owned(_) => "Owned",
            Cow::Borrowed(_) => "Borrowed",
        }
    }
}
/* Into<Cow> implementation */
impl<'a> From<Bar> for Cow<'a, Bar> {
    fn from(f: Bar) -> Cow<'a, Bar> {
        Cow::Owned(f)
    }
}
impl<'a> From<&'a Bar> for Cow<'a, Bar> {
    fn from(f: &'a Bar) -> Cow<'a, Bar> {
        Cow::Borrowed(f)
    }
}
/* Proof it works: */
fn main() {
    let bar = &Bar;
    assert_eq!(bar.hi(), "Borrowed");
    let bar = Bar;
    assert_eq!(bar.hi(), "Owned");
}

Borrow相比,一个优点是你知道数据是通过值还是引用传递的,如果这对你很重要的话。

最新更新