我如何实现一个我不拥有的特质,我不拥有?

时间:2014-08-20 19:45:20

标签: rust traits

我想为Shl实施Vec特征,代码如下。这样就可以使vec << 4成为可能,这对于vec.push(4)来说是个不错的选择。

use std::ops::Shl;

impl<T> Shl<T> for Vec<T> {
    type Output = Vec<T>;

    fn shl(&self, elem: &T) -> Vec<T> {
        self.push(*elem);
        *self
    }
}

fn main() {
    let v = vec![1, 2, 3];
    v << 4;
}

编译失败,出现以下错误:

  

无法提供扩展实现,其中特征和类型未在此包中定义[E0117]

  

类型参数T必须用作某些本地类型的类型参数(例如MyStruct<T>);只有当前包中定义的特征可以为类型参数[E0210]

实现

据我了解,我必须修补stdlib,更具体地来说是collections::vec箱子。有没有其他方法可以更改此代码以成功编译?

2 个答案:

答案 0 :(得分:31)

虽然你不能完全这样做,但通常的解决方法是在你自己的类型中包装你想要的类型并在其上实现特征。

use somecrate::FooType;
use somecrate::BarTrait;

struct MyType(FooType);

impl BarTrait for MyType {
    fn bar(&self) {
        // use `self.0` here
    }
}

答案 1 :(得分:9)

  

这样可以使vec << 4成为可能,这对于vec.push(4)来说是个不错的选择。

虽然可以这样做,但实现具有意外语义的运算符通常是bad idea

以下是如何完成此操作的示例:

use std::ops::Shl;

struct BadVec<T>(Vec<T>);

impl<T> Shl<T> for BadVec<T> {
    type Output = BadVec<T>;

    fn shl(mut self, elem: T) -> Self::Output {
        self.0.push(elem);
        self
    }
}

fn main() {
    let mut v = BadVec(vec![1, 2, 3]);
    v = v << 4;
    assert_eq!(vec![1, 2, 3, 4], v.0)
}

如果您实施DerefDerefMut):

use std::ops::{Deref, DerefMut};

impl<T> Deref for BadVec<T> {
    type Target = Vec<T>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<T> DerefMut for BadVec<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

您可以调用Vec方法:

fn main() {
    let mut v = BadVec(vec![1, 2, 3]);
    v = v << 4;
    v.truncate(2);
    assert_eq!(2, v.len());
}

看一下newtype_derive包,它可以为你生成一些样板代码。