OOP设计问题

Mar*_*cus 24 oop car-analogy

在这个简单的案例中,什么是好的设计:

假设我有一个基类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.

但是,如果你有一些使用多种燃料的神奇汽车,比如柴油或汽油呢?然后那辆车成为两者的子类,DieselCarGasCar你需要确保Car被声明为一个虚拟的超类,这样你就不能有两个Car在一个实例DualFuelCar对象.给油箱加油时应该只是很少或根本没有修改工作:在默认情况下,你会得到两个DualFuelCar.FillTank(GasFuel)DualFuelCar.FillTank(DieselFuel),给你一个重载按类型的功能.

但是,如果您不希望子类具有FillTank()函数,该怎么办?然后,您需要切换到运行时检查并执行您认为必须执行的操作:Fuel.type如果存在不匹配,请进行子类检查并抛出异常或返回错误代码(更喜欢后者).在C++中,RTTI dynamic_cast<>是我推荐的.在Python中isinstance().