【问题标题】:How do I store different types that implement the same trait in a vector and call common functions on them?如何在向量中存储实现相同特征的不同类型并在它们上调用常用函数?
【发布时间】:2016-04-01 13:46:36
【问题描述】:

我正在学习 Rust,但在实现多态时遇到了困难。我想使用一个数组来存储CircleTest

trait Poli {
    fn area(&self) -> f64;
}

struct Circle {
    x:      f64,
    y:      f64,
    radius: f64,
}

impl Circle {
    fn new (xx: f64, yy: f64, r: f64) -> Circle{
        Circle{ x: xx, y: yy, radius: r }
    }
}

impl Poli for Circle {
   fn area(&self) -> f64 {
       std::f64::consts::PI * (self.radius * self.radius)
   }
}

struct Test {
    x:      f64,
    y:      f64,
    radius: f64,
    test:   f64,
}

impl Test {
    fn new (xx: f64, yy: f64, r: f64, t: f64) -> Circle{
        Test{ x: xx, y: yy, radius: r, test: t, }
    }
}

impl Poli for Test {
    fn area(&self) -> f64 {
        std::f64::consts::PI * (self.radius * self.radius)
    }
}

我不知道如何制作一个向量来存储具有相同trait的类型:

let cir  = Circle::new(10f64, 10f64, 10f64);
let test = Test::new(10f64, 10f64, 10f64, 10f64);

//let mut vec: Vec<Poli> = Vec::new();   <---

我想迭代向量并从特征调用函数。有什么办法可以做到这一点,或者有什么替代方法?

我读了the trait object documentation,但我认为这不是我想要的。

【问题讨论】:

  • 我不认为这真的需要一个完整的答案,但是:特征对象正是你想要的(假设你想要开放多态性)。如果关闭是可以接受的,你需要一个enum。如果您不理解该章的某些方面,或者您可以解释为什么您认为这不是一个好的解决方案,添加它可能会改善问题。
  • @DK。对不起我的英语,我没有说从不 -> 为什么你认为这不是一个好的解决方案......只是说我正在阅读这个页面,但我找不到我想要的东西。事实证明,如果它在页面上,但我无法很好地理解这些示例来应用我正在寻找的东西。感谢您的宝贵时间

标签: polymorphism rust traits


【解决方案1】:

page you linked to 中所述,您需要将实现结构的Poli 存储为Vec&lt;&amp;Poli&gt;Vec&lt;Box&lt;Poli&gt;&gt;,具体取决于您是想拥有这些值还是只存储一个引用:

// Owned
let circle = Circle::new(10f64, 10f64, 10f64);
let test = Test::new(10f64, 10f64, 10f64, 10f64);

let polis = vec![Box::new(circle) as Box<Poli>, Box::new(test) as Box<Poli>];

for poli in polis {
    println!("{}", poli.area());
}

// Reference
let circle = Circle::new(10f64, 10f64, 10f64);
let test = Test::new(10f64, 10f64, 10f64, 10f64);

let polis = vec![&circle as &Poli, &test as &Poli];

for poli in polis {
    println!("{}", poli.area());
}

输出

314.1592653589793
314.1592653589793
314.1592653589793
314.1592653589793

Demo

【讨论】:

    【解决方案2】:

    Dogbert's response 之后,我玩了一下,发现这种方式对我有用。我是 Rust 新手,我不知道这是否显而易见,但我会把它留在这里以帮助其他人。

    let circle = Circle::new(10f64, 10f64, 10f64);
    let test   = Test::new(10f64, 10f64, 10f64, 10f64);
    
    let mut vec: Vec<&Poli> = Vec::<&Poli>::new();
        vec.push(&circle);
        vec.push(&test);
    
    for v in vec {
        println!("new {}", v.area());
    }
    

    Demo

    【讨论】:

    • 请注意,您不需要两次指定确切的类型:您可以删除 : Vec&lt;&amp;Poli&gt;::&lt;&amp;Poli&gt;
    猜你喜欢
    • 2023-01-05
    • 1970-01-01
    • 2018-11-16
    • 2019-07-14
    • 1970-01-01
    • 2019-11-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多