3

我想知道多重分派的概念(即内置支持,就好像虚拟方法的动态分派也扩展到方法的参数一样)是否应该包含在面向对象的语言中,如果它对性能的影响是微不足道。

问题

考虑以下场景:我有一个——不一定是扁平的——包含动物类型的类层次结构。在我的代码中的不同位置,我想对动物对象执行一些操作。我不关心,也无法控制如何获得这个对象引用。我可能会通过遍历动物列表遇到它,或者它可能作为方法的参数之一提供给我。我要执行的操作应该根据给定动物的运行时类型进行专门化。此类行动的示例包括:

  • 为动物构建一个视图模型,以便在 GUI 中显示它。
  • 构造一个表示这种动物的数据对象(稍后存储到数据库中)。
  • 给动物喂一些食物,但根据动物的类型给予不同种类的食物(什么对它更健康)

所有这些例子都在动物对象的公共 API 上操作,但它们所做的不是动物自己的事情,因此不能放入动物本身。

解决方案

一种“解决方案”是执行类型检查。但是这种方法容易出错并且使用反射特性,这(在我看来)几乎总是表明设计不好。类型应该只是一个编译时概念。

另一种解决方案是“滥用”(某种程度)访问者模式来模仿双重调度。但这需要我改变我的动物以接受访客。

我相信还有其他方法。另外,扩展的问题要解决:如果有新类型的动物加入聚会,需要调整多少代码位置,如何可靠地找到它们?

问题

那么,鉴于这些要求,多重分派不应该是任何设计良好的面向对象语言的一个组成部分吗?
使外部(不仅仅是内部)动作依赖于给定对象的动态类型不是很自然吗?

此致!

4

3 回答 3

0

一种“解决方案”是执行类型检查。但是这种方法容易出错并且使用反射特性,这(在我看来)几乎总是表明设计不好。类型应该只是一个编译时概念。

你错了。虚函数、虚继承等的所有使用都涉及反射特性和动态类型。当您需要时将输入推迟到运行时的能力是绝对关键的,并且即使是您所处情况的最基本表述也是固有的,如果不使用动态类型,实际上甚至无法出现。您甚至将您的问题描述为想要根据..动态类型做不同的事情。毕竟,如果没有动态类型,你为什么需要做不同的事情呢?您已经知道具体的最终类型。

当然,一些运行时类型可以解决你在运行时类型中遇到的问题。

只需构建一个从类型到函数的字典/哈希表。您可以为任何动态链接的派生类型动态地将条目添加到此结构中,这是一个很好的 O(1) 查找时间,并且不需要内部支持。

于 2015-05-26T18:38:34.207 回答
0

您建议基于方法名称/签名结合运行时实际参数类型进行动态调度。我觉得你疯了。

那么,鉴于这些要求,多重分派不应该是任何设计良好的面向对象语言的一个组成部分吗?

对于某些问题,您设想的那种调度策略的可用性将简化编码是一个弱论据,因为这种调度被内置到任何给定的语言中,更不用说每种OO 语言了。

使外部(不仅仅是内部)动作依赖于给定对象的动态类型不是很自然吗?

也许,但并非所有看起来“自然”的东西实际上都是一个好主意。例如,衣服不是天然的,但是如果你尝试在公共场合不穿衣服(无论如何,在伯克利以外的地方),看看会发生什么。

一些语言已经具有基于参数类型的静态调度,通常称为“重载”。另一方面,如果要考虑多个参数,则基于参数类型的动态调度是一团糟,而且它会很慢(呃)。当今流行的 OO 语言允许您在需要的地方执行双重调度,而无需在绝大多数不需要的地方支持它的开销。

此外,尽管实施双分派确实会出现由单独组件之间的紧密耦合引起的维护问题,但有一些编码策略可以帮助保持这种可管理性。无论如何,尚不清楚在给定语言中内置基于参数的多次调度实际上在多大程度上有助于解决该问题。

于 2015-05-26T18:46:36.577 回答
0

如果一个人将自己限制在这样一种情况,即 X 类型的对象应该如何定义 Y 类型的对象的知识必须存储在 X 类或 Y 类中,则可以让 Y 的基类型包含一个接受X 的基本类型,并指示对象知道如何被该引用标识的对象定义,以及要求对象对其进行定义的Y方法X

完成此操作后,可以先询问它对被特定类型X的. 如果知道的比知道的多,那么的方法应该调用 Y 的方法;否则,应该尽其所知。Fnorble(Y)YXYXXYXFnorble(Y)BeFnorbledBy(X)XY

根据有多少不同的种类X,可以为不同种类的 定义重载方法,这样在调用时它会自动直接分派给合适的方法;然而,这种方法将要求每个人都知道任何人都“感兴趣”的每一种类型,无论它是否对该特定类型本身感兴趣。YYBeFnorbledByXXtarget.BeFnorbledBy(this)YX

请注意,这种方法不适应可能存在类 Z 的外部对象的情况,该对象知道 X 应该如何定义 Y 的事情,而 X 和 Y 都不直接知道。这种情况最好通过拥有一个“规则手册”对象来处理,在该对象中,所有知道各种 X 应该如何定义各种 Y 的东西都可以告诉规则手册,并且想要 X 定义 Y 的代码可以询问规则手册做到这一点。尽管在规则手册是单例的情况下语言可以提供帮助,但有时拥有多个规则手册可能很有用。这些情况下的语义可能最好通过让代码直接使用规则手册来处理。

于 2015-05-26T18:48:30.427 回答