在这个简单的案例中,什么是好的设计:
假设我有一个基类Car,其中一种方法FillTank(Fuel fuel),燃料也是一个基类,有几个叶类,柴油,乙醇等.
在我的叶子车类上DieselCar.FillTank(Fuel fuel)只允许某种类型的燃料(没有意外:)).现在这是我的关注,根据我的界面,每辆车都可以装满任何燃料,但这对我来说似乎不对,在每次FillTank()实施中检查输入燃料的正确类型,如果没有抛出错误或其他什么.
我怎样才能将这种情况重新设计为更准确的情况,甚至可能吗?如何设计一个基本方法,在没有得到这些"奇怪结果"的情况下输入基类?
Kla*_*sen 28
使用通用基类(如果您的语言支持它(以下是C#)):
public abstract class Car<TFuel> where TFuel : Fuel
{
public abstract void FillTank(TFuel fuel);
}
Run Code Online (Sandbox Code Playgroud)
基本上,这会强制执行从汽车继承的任何类,以指定它使用的燃料类型.此外,Car该类强加了一个TFuel必须是抽象Fuel类的某个子类型的限制.
可以说我们有一些Diesel简单的类:
public class Diesel : Fuel
{
...
}
Run Code Online (Sandbox Code Playgroud)
还有一辆只用柴油的汽车:
public DieselCar : Car<Diesel>
{
public override void FillTank(Diesel fuel)
{
//perform diesel fuel logic here.
}
}
Run Code Online (Sandbox Code Playgroud)
Pet*_*der 12
仅面向对象的编程无法很好地处理这个问题.您需要的是通用编程(此处显示的C++解决方案):
template <class FuelType>
class Car
{
public:
void FillTank(FuelType fuel);
};
Run Code Online (Sandbox Code Playgroud)
那你的柴油车只是一辆特定的汽车Car<Diesel>.
Mik*_* D. 11
如果有车种和类型的燃料之间的硬边界,那么FillTank()有没有业务基础是Car一流的,因为知道你有车,不会告诉你的燃料是什么样的.因此,为了确保在编译时的 正确性,FillTank()应该在子类中定义,并且应该只采用有效的Fuel子类.
但是,如果您有不希望在子类之间重复的公共代码,该怎么办?然后为子类的函数调用的基类编写一个受保护的 FillingTank()方法.同样的事情Fuel.
但是,如果你有一些使用多种燃料的神奇汽车,比如柴油或汽油呢?然后那辆车成为两者的子类,DieselCar和GasCar你需要确保Car被声明为一个虚拟的超类,这样你就不能有两个Car在一个实例DualFuelCar对象.给油箱加油时应该只是很少或根本没有修改工作:在默认情况下,你会得到两个DualFuelCar.FillTank(GasFuel)和DualFuelCar.FillTank(DieselFuel),给你一个重载按类型的功能.
但是,如果您不希望子类具有FillTank()函数,该怎么办?然后,您需要切换到运行时检查并执行您认为必须执行的操作:Fuel.type如果存在不匹配,请进行子类检查并抛出异常或返回错误代码(更喜欢后者).在C++中,RTTI dynamic_cast<>是我推荐的.在Python中isinstance().