OO设计:使用属性还是重载方法?

时间:2011-01-05 17:24:04

标签: delphi oop

关于OO设计的问题。

假设我有一个基础对象车辆。还有两个后代:卡车和汽车。

此外,假设基础对象具有基本方法:

Procedure FixFlatTire(); abstract;

当卡车和汽车覆盖基础对象时,它们需要来自呼叫者的不同信息。

我最好在两个后代对象中重载像这样的FixFlatTire:

Procedure Truck.FixFlatTire( OfficePhoneNumber: String;
                             NumberOfAxles: Integer): Override; Overload;

Procedure Automobile.FixFlatTire( WifesPhoneNumber: String;
                                  AAAMembershipID: String): Override; Overload;

或者在每个后代中引入新属性,然后在调用FixFlatTire之前设置它们,如下所示:

Truck.OfficePhoneNumber := '555-555-1212';
Truck.NumberOfAxles := 18;
Truck.FixFlatTire();

Automobile.WifesPhoneNumber := '555-555-2323';
Automobile.AAAMembershipID  := 'ABC';
Automobile.FixFlatTire();

4 个答案:

答案 0 :(得分:5)

如果有问题的数据在逻辑上属于后代类(如果您可以在其他上下文中使用它们),那么将属性直接添加到后代类是有意义的。

如果它们严格适用于FixFlatTire方法,则将它们指定为该函数的参数更有意义。

如果你在后代类中提供了不同的方法签名,那么(据我所知)这不是一个重载的情况。您只是使用具有不同参数的新函数覆盖原始函数。重载是指两个具有相同名称的函数可用,由不同的签名区分。

[编辑]

仔细看看你的论点,这里有更多的想法:

  • NumberOfAxles显然似乎是TTruck的财产。

  • PhoneNumber和AAAMembershipID在我看来是你还没有的类的属性,TOwner(可能的后代类TCorporateOwner和TIndividualOwner)。然后,TOwner引用可以成为TVehicle的属性或FixFlatTire()的参数(虽然我认为它最好属于TVehicle的属性)。

答案 1 :(得分:3)

真正的错误是

FixFlatTire(); abstract;

当然应该是

FixFlatTire(); virtual; abstract;

启用多态行为。

您不应重载虚方法,只应覆盖保留方法的参数。


<强>更新

您不应该也不能超载虚拟方法。以下代码甚至无法编译:

type
  TVehicle = class
    procedure FixFlatTire(); virtual; abstract;
  end;

  TTruck = class(TVehicle)
    Procedure FixFlatTire( OfficePhoneNumber: String;
                             NumberOfAxles: Integer); Override; Overload;
  end;

  TAutomobile = class(TVehicle)
    Procedure FixFlatTire( WifesPhoneNumber: String;
                               AAAMembershipID: String); Override; Overload;
  end;

您应该在覆盖虚拟方法时保留虚方法的参数。

所以答案是 - 第一个选项(重载)是不可能的。

答案 2 :(得分:2)

我不会使用后者,因为有人设置一些属性并忘记稍后调用该方法很容易。第一个也是一个问题,因为你没有基类中每个方法的匹配签名。

OOP中的大多数问题都可以通过另一层抽象来解决。你可以在基类中拥有类似的东西,由汽车和卡车共享。

procedure FixFlatTire(TireProvider: ITireProvider); abstract; virtual;

ITireProvider可以使用OfficeTireProvider和AAATireProvider进行子类化,其中包含您需要为每个属性设置的相应属性,并且它们可以覆盖执行轮胎修复所需的ITireProvider的任何成员。

答案 3 :(得分:0)

具有属性的方法毫无意义。由于函数采用不同的参数,因此无法正确使用多态。您应该在具有适当参数的子类中使用不同的方法。

现在,如果你带回一个更复杂的版本,你只能在其中持有对基类的引用,那么就会调用另一个设计,但它不会是你目前提供的那个。