[英]Implementing trait with method returning generic trait
我試圖設計一對特征(例如來自線性代數的RowVector
和ColumnVector
),其中每個特征從其中一個方法返回另一個特征(例如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
生命周期?
你正試圖回歸一個特質。 雖然這可以使用特征對象 ,但它可能不是您想要做的。 更好的設計是引入Transpose
特性,您可以使用與Rust的內置From
和Into
轉換特征類似的方式進行建模。
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)
}
}
當需要關聯兩種類型時,最佳解決方案通常是關聯類型 。 這排除了使用像特征對象一樣的動態調度,但在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 }
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.