假设我需要模拟一些生物。所有生物都需要做一些事情:
trait LivingThing {
fn do_stuff(&self);
}
我可能有做不同事情的动物和植物这样的子特征,假设我这样模拟一个动物:
trait Animal {
fn do_other_stuff(&self);
fn food(&self) {
println!("Looking for food!");
}
}
impl LivingThing for dyn Animal {
fn do_stuff(&self) {
self.food();
self.do_other_stuff();
}
}
food
函数目前并不需要self
,但我只是想让事情简单化。do_other_stuff
函数的存在是为了确保子traits可以添加自己的功能,这些功能在调用do_stuff
函数时会自动调用。就像人类一样,例如:
struct Human {}
impl Animal for Human {
fn do_other_stuff(&self) {
println!("Taking a shower!");
}
}
现在,我可以这样做,以自动具有Human
功能以及Animal
功能。
let some_human = Human {};
LivingThing::do_stuff(&some_human as &dyn Animal);
// Prints: Looking for food!
// Taking a shower!
我不喜欢的是我不能这么做
let some_human = Human {};
some_human.do_stuff();
因为Human
没有实现LivingThing
特性。但是我觉得没有冲突,因为Human实现了Animal
,而它实现了LivingThing
。当然,Human
可以实现10个不同的traits,它们都实现了LivingThing
,但是如果只有一个实现,那么我应该很清楚我在尝试做什么。或者有没有更好的方法来添加do_stuff
的子特性功能?
到目前为止,我所做的是反转模型:让Human
实现LivingThing
和Animal
,并为Animal: LivingThing
设置一个traitbound。问题是,我需要记住从Human
调用Animal
的food
函数,这并不理想。
1条答案
按热度按时间luaexgnf1#
另一个选择是使用泛型为实现
Animal
的所有类型实现LivingThing
但是,在specialization稳定之前,这种方法意味着直接在任何实现
Animal
的类型(如Human
)上实现LivingThing
将导致实现冲突。