我声明了一个自定义特征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`
答案 0 :(得分:7)
Rust数组是同类的,这意味着它中的每个元素都具有相同的类型。因此,您无法拥有Dog
和Cat
s的数组。 但是你可以拥有一个充满所谓" trait objects"的数组,在你的情况下&Animal
。这就是我们如何显式请求运行时多态性。
您必须明确告诉编译器您需要一个充满特征对象的数组。编译器根据初始化程序中的第一个元素推断出数组的类型,所以让我们明确地转换那个东西:
let animals = [&Cat as &Animal, &Dog, &Cat, &Lion, &Dog, &Lion];
请注意,我们还为所有值添加了&
,因为您只能使用指向特征对象的指针。 (之后报告了代码中的另一个小错误,但解决方案相当简单)。 See on the playground
答案 1 :(得分:3)
这是因为Cat
,Dog
和Lion
都是不同的类型,而且您只能在数组中拥有一个。
你可以使用像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()
才能迭代数组。