简体   繁体   English

如何在 Rust 中定义 Vec 以支持包含实现相同特征的多种类型的结构?

[英]How to define a Vec in Rust to support containing multiple types of structs that implement a same trait?

In c++, I can define a parent class, and the type in vector can just be the father class type.在 c++ 中,我可以定义一个父 class,向量中的类型可以是父 class 类型。 So how to implement that in Rust?那么如何在 Rust 中实现呢?

Like for this example:就像这个例子:

I defined two types of Integer who both implement the trait Object, now I want to put them in a same vector, is there any way to achieve that?我定义了两种类型的 Integer,它们都实现了特征 Object,现在我想把它们放在同一个向量中,有什么办法可以实现吗?

pub trait Object<T: Object<T>+Clone> {
    fn sub(&self, x: &T) -> T {
        x.clone() //this is a useless implementation, just for structs don't need to implement this method.
    }
}

#[derive(Debug, Copy, Clone)]
pub struct Integer {
    val: i32
}

impl Integer {
    pub fn get(&self) -> i32 {
        self.val
    }

    pub fn new(val: i32) -> Self {
        Integer {
            val
        }
    }
}

#[derive(Debug, Copy, Clone)]
pub struct Int {
    val: i32
}

impl Int {
    pub fn get(&self) -> i32 {
        self.val
    }

    pub fn new(val: i32) -> Self {
        Int {
            val
        }
    }
}

impl Object<Int> for Int {
    fn sub(&self, rhs: &Int) -> Int {
        Int {
            val: self.val - rhs.get()
        }
    }
}


impl Object<Integer> for Integer {
    fn sub(&self, rhs: &Integer) -> Integer {
        Integer {
            val: self.val - rhs.get()
        }
    }
}

fn main() {
    let mut v: Vec<Box<dyn Object>> = Vec::new();
    v.push(Box::new(Integer::new(1)));
    v.push(Box::new(Int::new(2)));
}

Thanks a lot.非常感谢。

There are several aspects of your design that don't fit in Rust:你的设计有几个方面不适合 Rust:

  • trait Object<T: Object<T>+Clone> doesn't help - Rust doesn't do CRTP , just use Self instead. trait Object<T: Object<T>+Clone>没有帮助 - Rust 不做CRTP ,只用Self代替。
  • for Object to be object-safe (necessary to put it in a vector), it can't be parameterized by type.对于Object对象安全的(必须将其放入向量中),它不能按类型进行参数化。 A type parameter means you get a completely separate trait for each type.类型参数意味着您可以为每种类型获得完全独立的特征。
  • for the same reason, Object::sub() it can't return values by value - it should return Box<dyn Object> instead.出于同样的原因, Object::sub()它不能按值返回值 - 它应该返回Box<dyn Object>代替。

The code modified as indicated looks like this:按照指示修改的代码如下所示:

pub trait Object {
    fn get(&self) -> i32;
    fn sub(&self, x: &dyn Object) -> Box<dyn Object>;
}

#[derive(Debug, Copy, Clone)]
pub struct Integer {
    val: i32,
}

impl Integer {
    fn new(val: i32) -> Box<dyn Object> {
        Box::new(Int {val})
    }
}

impl Object for Integer {
    fn get(&self) -> i32 {
        self.val
    }

    fn sub(&self, rhs: &dyn Object) -> Box<dyn Object> {
        Integer::new(self.val - rhs.get())
    }
}

#[derive(Debug, Copy, Clone)]
pub struct Int {
    val: i32,
}

impl Int {
    fn new(val: i32) -> Box<dyn Object> {
        Box::new(Int {val})
    }
}

impl Object for Int {
    fn get(&self) -> i32 {
        self.val
    }

    fn sub(&self, rhs: &dyn Object) -> Box<dyn Object> {
        Int::new(self.val - rhs.get())
    }
}

fn main() {
    let mut v: Vec<Box<dyn Object>> = Vec::new();
    v.push(Integer::new(1));
    v.push(Integer::new(2));
    v.push(v[0].sub(v[1].as_ref()));
    for o in &v {
        println!("{}", o.get());
    }
}

Playground 操场

I think you can combine trait and provide a blank implementation, then use that in vector我认为您可以结合特征并提供一个空白实现,然后在向量中使用它

trait traitA {}
trait traitB {}
trait CombinedTraitATraitB: TraitA + TraitB {}
impl<T> CombinedTraitATraitB for T where T: TraitA + TraitB  {}

let vector: Vec<Box<dyn CombinedTraitATraitB>> = vec![];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM