rust 如何有效地“扩展”子traits中函数的功能?

b4lqfgs4  于 2023-02-04  发布在  其他
关注(0)|答案(1)|浏览(150)

假设我需要模拟一些生物。所有生物都需要做一些事情:

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实现LivingThingAnimal,并为Animal: LivingThing设置一个traitbound。问题是,我需要记住从Human调用Animalfood函数,这并不理想。

luaexgnf

luaexgnf1#

另一个选择是使用泛型为实现Animal的所有类型实现LivingThing

impl<T> LivingThing for T
where T: Animal {
    fn do_stuff(&self) {
        self.food();
        self.do_other_stuff();
    }
}

但是,在specialization稳定之前,这种方法意味着直接在任何实现Animal的类型(如Human)上实现LivingThing将导致实现冲突。

相关问题