0

我试图了解以下问题的答案在所有主要的 OOP 语言中是否相同;如果不是,那么这些语言有何不同。

假设我有A定义方法的类actjump;方法act调用方法jumpA的子类B覆盖方法jump(即,使用适当的语法来确保无论何时jump调用,B都使用类中的实现)。

我有b类的对象B。我希望它的行为就像它是类的一样A。换句话说,我希望jump使用A. 我有哪些不同语言的选择?

例如,我可以通过某种形式的向下转换来实现这一点吗?或者也许通过创建一个知道要调用哪些方法的代理对象?

我想避免创建一个全新的类对象A并仔细设置和之间的内部状态共享,a因为b这显然不是面向未来的,而且很复杂。我还想避免将状态复制b到一个全新的类对象中,A因为可能有很多数据要复制。

更新

我专门问了这个关于 Python的问题,但似乎这在 Python 中是不可能实现的,从技术上讲,它可以做到......有点......

似乎除了技术上的可行性之外,从设计的角度来看,还有一个强烈的反对这样做的论据。我在一个单独的问题中问这个问题

4

4 回答 4

2

评论重申:更喜欢组合而不是继承。

当您的子类与其超类有明确定义的行为差异时,继承效果很好,但是您经常会遇到该模型变得笨拙或不再有意义的地步。此时,您需要重新考虑您的设计。

组合通常是更好的解决方案。将对象的不同行为委托给不同的对象(或多个对象)可能会减少或消除您对子类化的需求。

在您的情况下,A 类和 B 类之间的行为差​​异可以封装在策略模式中。然后,您可以在实例级别更改 A 类(和 B 类,如果仍然需要)的行为,只需分配一个新策略即可。

策略模式在短期内可能需要更多代码,但它是干净且可维护的。方法调配、猴子补丁以及所有让我们在特定语言实现中四处游荡的很酷的东西都很有趣,但意外副作用的可能性很高,而且代码往往难以维护。

于 2012-01-17T16:39:18.633 回答
1

您要问的内容与 OOP 编程完全无关/不受支持。

如果您使用类对对象A进行子类B化并覆盖其方法,则在创建具体实例时B,基方法的所有覆盖/新实现都与它相关联(我们谈论 Java 或 C++ 与虚拟表等)。

你已经实例化了 object B
如果您已经覆盖了超类的方法,为什么您会期望您可以/将/应该能够调用该方法?

当然,您可以显式调用它,例如通过super在方法内部调用,但您不能自动执行此操作,并且强制转换也不会帮助您执行此操作。

我无法想象你为什么要这样做。
如果您需要使用 class ,请A使用 class A
如果您需要覆盖其功能,请使用它的子类B

于 2012-01-16T21:13:40.430 回答
0

大多数编程语言在支持虚函数的动态分派(在子类而不是父类的实现中调用被覆盖的方法的情况jump)方面遇到了一些麻烦——在某种程度上解决它或避免它是困难的。一般来说,专业化/多态性是一个理想的特性——可以说是 OOP 的首要目标。

查看有关Virtual Functions的 Wikipedia 文章,该文章对许多编程语言中对虚函数的支持进行了有用的概述。在考虑特定语言时,它将为您提供一个起点,以及在查看程序员可以控制分派行为方式的语言时权衡取舍(例如,参见 C++ 部分)。

如此松散地,您的问题的答案是,“不,所有编程语言的行为都不相同。” 此外,没有独立于语言的解决方案。如果您需要这种行为,C++ 可能是您最好的选择。

于 2012-01-16T21:16:42.113 回答
0

你实际上可以用 Python(有点)用一些可怕的 hack 来做到这一点。它要求您实现类似于我们在您的第一个 Python 特定问题中讨论的包装器,但作为 B 的子类。然后,您还需要实现写代理(包装器对象不应包含任何通常与类层次结构关联的状态,它应将所有属性访问重定向到 B 的底层实例。

但不是将方法查找重定向到 A 然后使用包装的实例调用该方法,而是调用将包装器对象传递为self. 这是合法的,因为包装器类是 B 的子类,因此包装器实例是您正在调用其方法的类的实例。

这将是非常奇怪的代码,要求您同时使用 IS-A 和 HAS-A 关系动态生成类。它也可能最终变得相当脆弱,并且在许多极端情况下会产生奇怪的结果(您通常不能完全在 Python 中编写 100% 完美的包装类,因为这种奇怪的事情是可能的)。

我完全不考虑天气这是否是个好主意。

于 2012-01-16T23:45:48.693 回答