首页 文章

用返回通用特征的方法实现特征

提问于
浏览
3

我试图设计一对特征(例如来自线性代数的 RowVectorColumnVector ),其中每个特征从其中一个方法返回另一个特征(例如 transpose ) . 我希望将来能够添加任何特征的实现(例如密集和稀疏矢量实现) .

#[macro_use]
extern crate derive_new;

trait RowVector<Element> {
    fn transpose(self) -> ColumnVector<Element>;
}

trait ColumnVector<Element> {
    fn transpose(self) -> RowVector<Element>;
}

#[derive(new, Debug)]
struct VecRowVector<Element> {
    vec: Vec<Element>
}

#[derive(new, Debug)]
struct VecColumnVector<Element> {
    vec: Vec<Element>
}

impl<Element> RowVector<Element> for VecRowVector<Element> {
    fn transpose(self) -> VecColumnVector<Element> {
        VecColumnVector::new(self.vec)
    }
}

impl<Element> ColumnVector<Element> for VecColumnVector<Element> {
    fn transpose(self) -> VecRowVector<Element> {
        VecRowVector::new(self.vec)
    }
}

fn main() {
    let row_vector = VecRowVector::new(vec![1,2,3]);
    let col_vector = VecColumnVector::new(vec![1,2,3]);
    println!("{:?}", row_vector.transpose());
    println!("{:?}", col_vector.transpose());
}

我得到一个错误,说 VecColumnVector 不是 ColumnVector ,它期望 'static 值 .

error[E0053]: method `transpose` has an incompatible type for trait
  --> src\main.rs:22:31
   |
4  |         fn transpose(self) -> ColumnVector<Element>;
   |                               --------------------- type in trait
...
22 |         fn transpose(self) -> VecColumnVector<Element> {
   |                               ^^^^^^^^^^^^^^^^^^^^^^^^ expected trait ColumnVector, found struct `VecColumnVector`
   |
   = note: expected type `fn(VecRowVector<Element>) -> ColumnVector<Element> + 'static`
   = note:    found type `fn(VecRowVector<Element>) -> VecColumnVector<Element>`

我没有 VecColumnVector ColumnVector 的子类型?或者我是否需要告诉特性它不需要是 static 生命周期?

2 回答

  • 1

    你正试图回归一个特质 . 虽然这可以使用trait object,但它可能不是你想要做的 . 更好的设计是引入一个 Transpose 特征,你可以用与Rust的内置 FromInto 转换特征类似的方式建模 .

    trait Transpose<To> {
        fn transpose(self) -> To;
    }
    
    impl<Element> Transpose<VecColumnVector<Element>> for VecRowVector<Element> {
        fn transpose(self) -> VecColumnVector<Element> {
            VecColumnVector::new(self.vec)
        }
    }
    
    impl<Element> Transpose<VecRowVector<Element>> for VecColumnVector<Element> {
        fn transpose(self) -> VecRowVector<Element> {
            VecRowVector::new(self.vec)
        }
    }
    
  • 2

    当需要关联两种类型时,最佳解决方案通常是associated types . 这排除了使用像特征对象一样的动态调度,但在Rust中动态调度仍然非常有限 . 使用静态调度时,Rust更具表现力,相关类型具有杠杆作用 .

    pub trait RowVector<Element>: Sized {
        type Transpose: ColumnVector<Element>;
    
        fn transpose(self) -> Self::Transpose;
    }
    
    pub trait ColumnVector<Element>: Sized {
        type Transpose: RowVector<Element>;
    
        fn transpose(self) -> Self::Transpose;
    }
    
    pub struct VecRowVector<Element> {
        pub vec: Vec<Element>
    }
    
    pub struct VecColumnVector<Element> {
        pub vec: Vec<Element>
    }
    
    impl<Element> RowVector<Element> for VecRowVector<Element> {
        type Transpose = VecColumnVector<Element>;
    
        fn transpose(self) -> VecColumnVector<Element> {
            VecColumnVector { vec: self.vec }
        }
    }
    
    impl<E: Debug> ColumnVector<Element> for VecColumnVector<Element> {
        type Transpose = VecRowVector<Element>;
    
        fn transpose(self) -> VecRowVector<Element> {
            VecRowVector { vec: self.vec }
        }
    }
    

相关问题