在我知道的C++和大多数面向对象的语言中,当从现有类A派生类B时,可以添加新方法,覆盖现有方法并添加新数据成员。如果A在B中有一些你不想要的东西,那么你不能消除它们。也许大多数情况下,这无关紧要,但我曾经有些时候希望我能做到。是否有OO语言允许从课程中减去功能?
是否有任何语言确实允许派生类被定义为其父元素的某些元素被删除?
在我知道的C++和大多数面向对象的语言中,当从现有类A派生类B时,可以添加新方法,覆盖现有方法并添加新数据成员。如果A在B中有一些你不想要的东西,那么你不能消除它们。也许大多数情况下,这无关紧要,但我曾经有些时候希望我能做到。是否有OO语言允许从课程中减去功能?
是否有任何语言确实允许派生类被定义为其父元素的某些元素被删除?
我想也许正确的方法来做这个子类应该提供一个空方法,覆盖父的实现。
问题是子类与它们的超类有IS-A关系。如果子类取消了方法,在语义上它会是超类的一个实例吗?多态性如何工作?当你将一个子类传递给一个期望超类类型的方法时,你会遇到各种各样的痛苦,你应该能够做到这一点。
这就是说,使用动态语言,您可以通过元编程在运行时删除所需的方法。但是我只是做一个空方法,如果有意义的话可能会抛出一些UnsupportedOperation错误。
那么......如果你遵循“面向方面编程”技术并使用接口,那么你应该能够有效地“隐藏”你不希望用户看到的实现细节,因为他们只能访问到接口的成员
如果需要从父类(或父对象,它也适用于原型OO)中删除功能,它不应该继承首先。见Liskov substitution principle:
的子类型设q(x)为可证明的关于对象的属性类型T.则Q(Y)的X应为S型的对象ý真其中S是T.
或者,去了 “是”:如果从B
D
继承,那么每D
是B
。如果它没有其方法之一,则不能是B
。
而且,实际的问题:这基本上使亚型多态性(能够通过一个D
每当需要一个A
/预期),面向对象的非常基本的功能,是不可能的(因为你无法知道是否亚型也暴露某种方法/财产)。
假设B是基本的,D是派生的,那么你是不是应该说:“如果D从B继承,那么每个D都是B.如果没有它的方法之一,它就不能成为B. “ – JeremyP 2010-12-15 17:00:25
@JeremyP:是的,谢谢。 – delnan 2010-12-15 17:10:55
LSP很重要,但我继承的tanglewad OO应用程序似乎将新类定义为像某些现有类,但是有了这个和这个,没有这个和其他的东西。类之间的差异被定义为用另一个类来定义一个类,而不是一个适当的继承关系,而不是替代的意图。奇怪,丑陋,但这是我们正在努力。 – DarenW 2011-09-29 05:20:18
有些情况下,你可以得到一些东西类似这个。
例如,在Windows窗体,所有控件的属性显示在属性网格,这样你就可以在可视化设计器编辑它们的值。 Control基类暴露了一堆共同属性,如文本,这并不适用于所有控件的,但(在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。 (他们可以为每个这些共同属性创建一个接口,这将允许后代选择支持它们,同时让代码访问它们而不向下转换为特定控件类型。)
使用面向方面编程几乎可以做一些类似于你说的话。有很多针对此的语言,例如AspectJ。 无论如何,我想你应该考虑一个事实,那就是你可能设计了一个糟糕的体系结构,因为做这种事情可能会降低软件的可伸缩性(类并不总是提供连贯的服务)的质量。 面向对象编程是另一个研究领域,旨在完成您的建议。
override-and-throw模式广泛用于.NET框架类库中。例如,'ReadOnlyCollection'将为所有由IList 接口契约规定的变异方法抛出'NotSupportedException'。除此之外,没有任何事情可以合理地完成。 –
cdhowie
2010-12-15 16:12:34
Java在java.util中与它的集合做同样的事情。请参见java.lang.UnsupportedOperationException。 – orangepips 2010-12-15 19:47:42
@orangepips是正确的 - 但问题是一般的OO,而不是Java特定的。所以我只是采取了一点,通过它我的答案,但它使一般;) – hvgotcodes 2010-12-15 19:55:50