在C ++和大多数面向对象的语言中,我知道,当您从现有的A类派生B类时,您可以添加新方法,覆盖现有方法以及添加新数据成员。如果A在B中有一些你不想要的碎片,你就无法消除它们。也许大多数时候无论如何都没有意义,但有时候我希望我能做到。
是否有任何语言允许定义派生类并删除其某些父元素?
答案 0 :(得分:5)
我认为也许正确的方法,子类应该提供一个覆盖父实现的空方法。
问题是子类与其超类之间存在IS-A关系。如果子类关闭了方法,那么在语义上它是否是超类的一个实例?多态性如何工作?当你将一个子类传递给一个期望超类类型的方法时,你会遇到各种各样的痛苦,你应该能够做到这一点。
也就是说,使用动态语言,您可以通过元编程在运行时删除所需的方法。但我只是做一个空方法,如果有意义,可能会抛出某种UnsupportedOperation错误。
答案 1 :(得分:3)
如果需要从父类(或父对象,也适用于原型OO)中删除功能,它不应该首先继承。见Liskov substitution principle:
设q(x)是可证明类型为T的对象x的属性。对于S类型的对象y,q(y)应该为真,其中S是T的子类型。
或者,过去“是一个”:如果D
继承自B
,那么每个D
都是 B
。如果它没有其中一种方法,则它不能是B
。
另外,实际问题:这基本上会产生子类型多态性(只要D
需要/期望就能传递A
),这是OO的一个非常基本的特征,不可能(因为你可以不知道子类型是否也暴露了某种方法/属性。
答案 2 :(得分:1)
在某些情况下,您可以获得类似的内容。
例如,在Windows窗体中,所有控件的属性都显示在属性网格中,因此您可以在可视化设计器中编辑它们的值。基类Control类公开了一堆常见的属性,比如Text,它们不适用于所有控件,但是(在Windows窗体团队的视图中)是足够通用的,你应该可以在控件上设置它们必须知道它是按钮,标签,窗口等。
虽然你实际上无法在后代类中删除这些属性 - 如果你真的想要代码仍然可以读取和写入它们 - 你可以用属性标记它们以告诉工具隐藏它们,这样至少,他们不在你的路上。
// Don't show this property in the Property Grid
[Browsable(false)]
// Don't save this property's design-time value to be reloaded at runtime
// (i.e. don't generate a property assignment in the .designer.cs file)
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
// Don't show this property in the editor's Intellisense code-completion lists
[EditorBrowsable(EditorBrowsableState.Never)]
public override string Text {
get { return base.Text; }
set { base.Text = value; }
}
当然,可以说,只是因为设计很差,他们必须创造这些属性 - 这种设计显然违反了Liskov Substitution Principle。 (相反,他们可以为这些公共属性中的每一个创建一个接口,这样可以让后代选择支持它们,同时仍允许代码访问它们而不向下转换为特定的控件类型。)
答案 3 :(得分:1)
使用面向方面编程,您几乎可以做与您所说的相似的事情。有许多语言针对此,例如AspectJ。 无论如何,我想你应该考虑很好的事实,你可能正在设计一个糟糕的架构,因为做这种事情可能会降低你的软件质量,从而无法实现(不总是提供连贯服务的类)。 面向主题的编程是另一个旨在做你所建议的研究领域。
答案 4 :(得分:0)
嗯......如果您遵循“面向方面编程”技术并使用接口,那么您应该能够有效地“隐藏”您不希望用户看到的实现细节,因为他们只能访问界面成员