【发布时间】:2021-05-09 05:59:56
【问题描述】:
我知道我应该使用组合而不是继承。
在 Java/C++ 中,我有一个抽象基类 Vehicle(带有属性和常用方法)和实现它的类,例如 Car 和 Bike。
我找到了enum_dispatch,它在将方法调用从父“类”转发到子“类”方面做得很好。
#[enum_dispatch]
pub trait VehicleDelegation {
fn drive(&mut self) -> anyhow::Result<()>;
}
#[enum_dispatch(VehicleDelegation)]
pub enum Vehicle {
Car,
Bike,
}
pub struct Car {
pub doors: u8
}
impl VehicleDelegation for Car {
fn drive(&mut self) -> anyhow::Result<()> {
// do car stuff
Ok(())
}
}
pub struct Bike {
pub frame_size: u8
}
impl VehicleDelegation for Bike {
fn drive(&mut self) -> anyhow::Result<()> {
// do bike stuff
Ok(())
}
}
- 我应该在哪里存储公共数据,例如
num_wheels,它本来是Vehicle的属性? - 我应该在哪里定义
Vehicle使用公共数据的方法?
目前我必须将所有 Vehicle 数据和方法复制到每个枚举变体中,这变得越来越烦人,因为它会随着“方法”的数量和“类”的数量而增加。
- 如何在 Rust 中以惯用方式做到这一点?
【问题讨论】:
-
你可以有一个结构,其中一个字段是你上面的
Vehicle枚举;公共数据的其他字段,并为公共方法在该结构上实现实现。 -
@eggyal 谢谢,我考虑过这一点,但是
Vehicle枚举变体如何访问它们共同的父级数据?这需要为mut工作,因此在枚举变体中保留对父级的引用是行不通的。 -
我投票“需要详细信息”,但真正的问题是
Vehicle/Bike等只是一个玩具示例;它是纯粹的结构。它不能解决真正的问题,因此不可能就如何改进它提出明智的建议。 您不能将程序的设计与其解决的问题分开。 像这样的玩具示例的主要作用是演示继承如何工作,而这根本不可能在 Rust 中完成,因为 Rust 没有继承。 -
如果您在设计一些解决问题的程序时遇到困难,而不仅仅是从 Java 书籍或任何演示继承的玩具程序,仅此而已,为了回答这个问题,我们需要通知设计的要求和约束。其他一切都是浪费时间。请记住,大多数微小的、琐碎的程序都不够复杂,不需要像继承这样的复杂特性;需求源于复杂性,因此架构问题的minimal reproducible example 通常比语法错误要大得多。
-
@trentcl 谢谢,我同意你的观点,但没有明显的解决方案。我问了一个玩具问题,因为我认为发布数百行特定于域的代码会使问题变得难以理解。 (我想我已经想出了一个可行的解决方案,我打算将它与一个“玩具”插图一起发布,如果它能够在几天的开发中存活下来。)
标签: inheritance rust enums dispatch enum-dispatch