Oop 有任何OO语言允许从类中减去特性吗? 在C++和大多数面向对象的语言中,我知道,当你从现有的类A中派生B类时,你可以添加新的方法,重写现有的方法,并添加新的数据成员。如果A在B中有一些你不想要的片段,你就不能消除它们。也许大多数时候这都没有意义,但有时我希望我能做到

Oop 有任何OO语言允许从类中减去特性吗? 在C++和大多数面向对象的语言中,我知道,当你从现有的类A中派生B类时,你可以添加新的方法,重写现有的方法,并添加新的数据成员。如果A在B中有一些你不想要的片段,你就不能消除它们。也许大多数时候这都没有意义,但有时我希望我能做到,oop,programming-languages,Oop,Programming Languages,是否有任何语言允许在删除父类的某些元素的情况下定义派生类?那么。。。如果您遵循“面向方面编程”技术并使用接口,那么您应该能够有效地“隐藏”您不希望用户看到的实现详细信息,因为他们只能访问接口的成员我认为这样做的正确方法可能是子类应该提供一个覆盖父级实现的空方法 问题是子类与它们的超类之间存在一种is-A关系。如果子类去掉了方法,在语义上它会是超类的一个实例吗?多态性是如何工作的?当您将一个子类传递给一个需要超类类型的方法时,您会遇到各种各样的麻烦,您应该能够做到这一点 也就是说,使用动态语言,您

是否有任何语言允许在删除父类的某些元素的情况下定义派生类?

那么。。。如果您遵循“面向方面编程”技术并使用接口,那么您应该能够有效地“隐藏”您不希望用户看到的实现详细信息,因为他们只能访问接口的成员

我认为这样做的正确方法可能是子类应该提供一个覆盖父级实现的空方法

问题是子类与它们的超类之间存在一种is-A关系。如果子类去掉了方法,在语义上它会是超类的一个实例吗?多态性是如何工作的?当您将一个子类传递给一个需要超类类型的方法时,您会遇到各种各样的麻烦,您应该能够做到这一点


也就是说,使用动态语言,您可以通过元编程在运行时删除所需的方法。但我只会执行一个空方法,如果有意义的话,它可能会抛出某种不支持的操作错误。

如果它需要从父类(或父对象,也适用于原型OO)中删除功能,它首先不应该继承。见:

设q(x)是关于T类型的对象x的可证明的属性。那么对于S类型的对象y,q(y)应该为真,其中S是T的子类型

或者,检查“是a”:如果
D
继承自
B
,则每个
D
都是a
B
。如果没有一个方法,它就不能是a
B


另外,实际问题:这基本上会使子类型多态性(无论何时需要/期望
a
,都能传递
D
)成为OO的一个基本特性,这是不可能的(因为您不知道子类型是否也公开了某个方法/属性).

在某些情况下,您可以获得类似的结果

例如,在Windows窗体中,控件的所有属性都显示在属性网格中,因此您可以在可视化设计器中编辑它们的值。基本控件类公开了一系列公共属性,如文本,这些属性并不适用于所有控件,但(在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; }
}

当然,有人可能会说,仅仅是因为糟糕的设计,他们才不得不创建这些属性——这种设计显然违反了标准。(相反,他们可以为这些公共属性中的每一个创建一个接口,让后代选择支持它们,同时仍然允许代码访问它们,而无需向下转换到特定的控件类型。)

使用面向方面的编程,您实际上可以做类似于您所说的事情。有许多语言针对这一点,例如AspectJ。 不管怎样,我想你应该好好考虑一下你可能设计出一个糟糕的架构,因为这样做可能会降低软件的质量(不总是提供连贯的服务)。
面向主题的编程是另一个研究领域,旨在实现您的建议。

重写和抛出模式在.NET framework类库中广泛使用。例如,
ReadOnlyCollection
将抛出
NotSupportedException
,用于由
IList
接口契约指定的所有变异方法。实际上没有其他合理的方法可以做,Java在Java.util中对其集合也做了同样的事情。请参阅java.lang.UnsupportedOperationException.@orangepips是对的——但问题是一般的OO,而不是java特有的。所以我只是把这一点作为我的答案,但把它概括起来;)与您不矛盾的是,注意Java做的事情与.NET:)相同。假设B是基,D是派生的,您是否应该说:“如果D从B继承,那么每个D都是B。如果它没有一个方法,它就不可能是B。”LSP很重要,但我继承的tanglewad OO应用程序似乎将新类定义为类似于一些现有类,但有这个和这个,没有那个和其他东西。类之间的一种增量,用于根据另一个类定义一个类,而不是一个正确的继承关系,没有替换的意图。奇怪,丑陋,但这是我们正在研究的。