我正在处理一个大型代码库,它在这些类上有很多类和很多抽象方法。我对以下情况下我应该做些什么的人们有兴趣。
如果我有一个带有抽象方法的Parent-A类。只有2个孩子。如果Child-B实现了AbstractMethodA但Child-B没有实现,因为它不适用。
我应该
编辑:感谢您的所有答案。它证实了我的怀疑,这不应该发生。经过进一步调查后发现这些方法根本没有使用,所以我完全删除了它们。
答案 0 :(得分:9)
如果AbstractMethodA不适用于Child-B,那么Child-B不应该从Parent-A继承。
或者采取相反的观点,如果Child-B继承自Parent-A,而AbstractMethodA不适用于子女,那么它也不应该在父母中。
通过在Parent-A中放置一个方法,您说该方法适用于Parent-A及其所有子项。这就是继承意味着什么,如果你用它来表示不同的东西,你最终会与你的编译器发生严重争议。
[编辑 - 那说,如果该方法适用,Mladen Prajdic的答案很好,但是对于所涉及的一个或多个类别不应该做任何事情。一无所取的方法是IMO与不适用的方法不同,但也许我们并不是指“不适用”的相同的事情。]
另一种技术是在Child-B中实现该方法,但让它做一些激烈的事情,如总是返回失败,或抛出异常,或其他东西。它可以工作,但应该被认为是一种躲闪而不是干净的设计,因为这意味着呼叫者需要知道他们所拥有的他们正在将其视为Parent-A的东西真的一个孩子-B因此他们不应该调用AbstractMethodA。基本上你已经抛弃了多态性,这是OO继承的主要好处。就个人而言,我更喜欢这样做,而不是在基类中抛出异常,因为子类不能通过“忘记”实现该方法而“意外地”表现得很糟糕。它必须实现它,如果它实现它不工作,那么它明确地这样做。糟糕的情况应该是吵闹。
答案 1 :(得分:2)
如果后代中的实现不是强制性的,那么你应该去1 + 2(即祖先的空虚方法)
答案 2 :(得分:1)
我认为,一般来说,如果你不能首先实现所有的抽象方法,你不应该继承抽象类,但是我知道在某些情况下仍然有意义这样做,(参见Stream类及其实现)。
我认为你应该只创建抛出NotImplementedException的这些抽象方法的实现。
您也可以尝试使用ObsoleteAttribute,以便调用该特定方法将是编译时错误(当然,抛出NotImplementedException)。请注意,ObsoleteAttribute并不适合用于此目的,但我想如果您使用带有注释的有意义的错误消息,那就没关系。
强制性代码示例:
[Obsolete("This class does not implement this method", true)]
public override string MyReallyImportantMethod()
{
throw new NotImplementedException("This class does not implement this method.");
}
答案 3 :(得分:0)
在基类中将其设为虚拟,并在子类中覆盖它。
答案 4 :(得分:0)
您可以使用界面。然后,Child-A和Child-B都可以实现不同的方法,并且仍然继承自Parent-A。接口像抽象方法一样工作,因为它们强制类实现它们。
答案 5 :(得分:0)
如果A的某些子类(B1,B2,...)用于其方法的不同子集(C1,C2,...),可以说A可以在B和C中拆分
我不太熟悉Delphi(根本不是:)),但我认为就像例如在Java和COM中,类可以“实现”多个接口。在C ++中,这只能通过多次继承抽象类来实现。
更具体:我将创建两个抽象类(使用抽象方法),并更改继承树。
如果不可能,则解决方法可能是“适配器”:中间类A_nonB_,其中所有B方法都实现为空(并在调用它们时产生警告)和A_nonC_。然后更改继承树以解决您的问题:B1,B2,...继承自A_nonC_和C1,C2,...继承自A_NonB _。