2011-01-05 57 views
0

关于OO设计的问题。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

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

现在,如果你回来了一个更复杂的版本,其中你只持有对基类的引用,那么将会要求一个不同的设计,但它将不是迄今为止提供的设计。

+0

“你不能正确使用多态性,因为函数采用不同的参数。”啊哈!这就是我意识到的困扰我,我现在意识到你拼写出来了,大卫! (通过点击 -key过早发布此评论。)使用此设计的代码将必须知道它的后代,因此使用属性保留方法的签名没有任何优势。感谢您为我阐述了这一点。 – RobertFrank 2011-01-05 19:24:39

+0

我不一定认为房产的做法是_correct_,但它为什么没有意义?如果您知道该类将具有执行FixFlatTire操作所需的属性,则每个后代类都可以实现无参数的FixFlatTire()方法。 – 2011-01-05 19:27:31

+0

@Larry @Robert这是没有意义的,因为与两种独立方法的方法相比,没有什么优点和缺点。至少这是我的看法。 – 2011-01-05 19:29:20

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; 

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

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

+0

同意:这是一个错误,Serg。但是,修正了这个问题后,我的问题仍然是我是否应该通过属性传递必要的信息,或者通过两种不同参数的方法。 – RobertFrank 2011-01-05 17:45:31

+1

@罗伯特通过两种不同参数的方法,用来传递参数的状态确实是邪恶的,在我看来 – 2011-01-05 19:08:24

+0

并不是说超载在这里是正确的选择,但是你说的是不正确的。有可能超载虚拟功能。您的示例没有编译的原因是没有继承的重载虚拟方法(具有匹配的签名)以供overRIDE指令应用。 – Deltics 2011-01-06 04:17:21

5

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

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

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

[编辑]

看着你的论点有点接近,这里有更多的想法:

  • NumberOfAxles很显然似乎是TTruck的属性。

  • PhoneNumber和AAAMembershipID对我来说似乎是你还没有的类的属性,TOwner(带有可能的后代类TCorporateOwner和TIndividualOwner)。然后,一个TOwner参考可以成为TVehicle的一个属性或FixFlatTire()的一个参数(尽管我想它最好属于TVehicle的一个属性)。

2

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

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

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

ITireProvider可以与OfficeTireProvider和AAATireProvider,其含有需要为每个设置的各自的属性作为子类,并且它们可以覆盖ITireProvider的任何成员需要做实际的轮胎固定。