为什么我不能在数组声明中使用类型推断?

时间:2016-09-12 13:42:59

标签: arrays polymorphism rust

我声明了一个自定义特征Animal的数组,以便在Rust中试验多态,但编译器似乎对第一个元素的子类型进行了类型推断:

fn main() {
    let animals = [Cat, Dog, Cat, Lion, Dog, Lion];
    for single_animal in animals {
        single_animal.talk();
    }
}

trait Animal {
    fn talk(&self);
}

struct Cat;
struct Dog;
struct Lion;

impl Animal for Cat {
    fn talk(&self) { 
        println!("Je miaule !");
    }
}

impl Animal for Dog {
    fn talk(&self) { 
        println!("J'aboie !");
    }
}

impl Animal for Lion {
    fn talk(&self) {
        println!("Je rugit !");
    }
}

编译器抱怨第一个元素是Cat而不是其他元素:

error: mismatched types [--explain E0308]
 --> src/main.rs:3:25
  |>
3 |>     let animals = [Cat, Dog, Cat, Lion, Dog, Lion];
  |>                         ^^^ expected struct `Cat`, found struct `Dog`
note: expected type `Cat`
note:    found type `Dog`

error: mismatched types [--explain E0308]
 --> src/main.rs:3:35
  |>
3 |>     let animals = [Cat, Dog, Cat, Lion, Dog, Lion];
  |>                                   ^^^^ expected struct `Cat`, found struct `Lion`
note: expected type `Cat`
note:    found type `Lion`

error: mismatched types [--explain E0308]
 --> src/main.rs:3:41
  |>
3 |>     let animals = [Cat, Dog, Cat, Lion, Dog, Lion];
  |>                                         ^^^ expected struct `Cat`, found struct `Dog`
note: expected type `Cat`
note:    found type `Dog`

error: mismatched types [--explain E0308]
 --> src/main.rs:3:46
  |>
3 |>     let animals = [Cat, Dog, Cat, Lion, Dog, Lion];
  |>                                              ^^^^ expected struct `Cat`, found struct `Lion`
note: expected type `Cat`
note:    found type `Lion`

error: the trait bound `[Cat; 6]: std::iter::Iterator` is not satisfied [--explain E0277]
 --> src/main.rs:4:5
  |>
4 |>     for single_animal in animals {
  |>     ^
note: `[Cat; 6]` is not an iterator; maybe try calling `.iter()` or a similar method
note: required by `std::iter::IntoIterator::into_iter`

向数组中添加Animal类型也无法解决问题。因为这次我得到更多错误:

error: mismatched types [--explain E0308]
 --> src/main.rs:3:27
  |>
3 |>     let animals: Animal = [Cat, Dog, Cat, Lion, Dog, Lion];
  |>                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait Animal, found array of 6 elements
note: expected type `Animal`
note:    found type `[Cat; 6]`

error: the trait bound `Animal: std::marker::Sized` is not satisfied [--explain E0277]
 --> src/main.rs:3:9
  |>
3 |>     let animals: Animal = [Cat, Dog, Cat, Lion, Dog, Lion];
  |>         ^^^^^^^
note: `Animal` does not have a constant size known at compile-time
note: all local variables must have a statically known size

error: the trait bound `Animal: std::marker::Sized` is not satisfied [--explain E0277]
 --> src/main.rs:4:5
  |>
4 |>     for single_animal in animals {
  |>     ^
note: `Animal` does not have a constant size known at compile-time
note: required by `std::iter::IntoIterator::into_iter`

error: the trait bound `Animal: std::iter::Iterator` is not satisfied [--explain E0277]
 --> src/main.rs:4:5
  |>
4 |>     for single_animal in animals {
  |>     ^
note: `Animal` is not an iterator; maybe try calling `.iter()` or a similar method
note: required by `std::iter::IntoIterator::into_iter`

2 个答案:

答案 0 :(得分:7)

Rust数组是同类的,这意味着它中的每个元素都具有相同的类型。因此,您无法拥有DogCat s的数组。 但是你可以拥有一个充满所谓" trait objects"的数组,在你的情况下&Animal。这就是我们如何显式请求运行时多态性。

您必须明确告诉编译器您需要一个充满特征对象的数组。编译器根据初始化程序中的第一个元素推断出数组的类型,所以让我们明确地转换那个东西:

let animals = [&Cat as &Animal, &Dog, &Cat, &Lion, &Dog, &Lion];

请注意,我们还为所有值添加了&,因为您只能使用指向特征对象的指针。 (之后报告了代码中的另一个小错误,但解决方案相当简单)。 See on the playground

答案 1 :(得分:3)

这是因为CatDogLion都是不同的类型,而且您只能在数组中拥有一个。

你可以使用像Lukas建议的特质对象,但你可以更容易地实现你想要的东西(特质对象不是我推荐给Rust初学者的东西),有一个共同的Animal枚举:< / p>

use self::Animal::*;

fn main() {
    let animals = [Cat, Dog, Cat, Lion, Dog, Lion];
    for single_animal in animals.iter() {
        single_animal.talk();
    }
}

trait AnimalSkills {
    fn talk(&self);
}

enum Animal {
    Cat,
    Dog,
    Lion
}

impl AnimalSkills for Animal {
    fn talk(&self) {
        match *self {
            Cat => println!("Je miaule !"),
            Dog => println!("J'aboie !"),
            Lion => println!("Je rugit !")
        }
    }
}

另请注意,您需要调用.iter()才能迭代数组。