关于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();
答案 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)
具有属性的方法毫无意义。由于函数采用不同的参数,因此无法正确使用多态。您应该在具有适当参数的子类中使用不同的方法。
现在,如果你带回一个更复杂的版本,你只能在其中持有对基类的引用,那么就会调用另一个设计,但它不会是你目前提供的那个。