Yes, but not that easily. What you've written there is that animal
should be a variable of type Barks
, but Barks
is a trait; a description of an interface. Traits don't have a statically-defined size, since a type of any size could come along and impl Barks
. The compiler has no idea how big to make animal
.
What you need to do is add a layer of indirection. In this case, you can use Box
, although you can also use things like Rc
or plain references:
fn main() {
let animal: Box<dyn Barks>;
if 1 == 2 {
animal = Box::new(Dog);
} else {
animal = Box::new(Wolf);
}
animal.bark();
}
Here, I'm allocating the Dog
or Wolf
on the heap, then casting that up to a Box<dyn Barks>
. This is kind of like casting an object to an interface in something like C# or Java, or casting a Dog*
to a Barks*
in C++.
An entirely different approach you could also use would be enums. You could have enum Animal { Dog, Wolf }
then define an impl Animal { fn bark(&self) { ... } }
. Depends on whether you need a completely open-ended set of animals and/or multiple traits.
Finally, note that "kind of" above. There are various things that don't work as they would in Java/C#/C++. For example, Rust doesn't have downcasting (you can't go from Box<dyn Barks>
back to Box<Dog>
, or from one trait to another). Also, this only works if the trait is "object safe" (no generics, no using self
or Self
by-value).
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…