问题标签 [double-dispatch]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
4 回答
145 浏览

c# - 在动态双重调度之前检查类型可见性

使用以下方式实现双重调度dynamic

在大多数情况下有效:

完成一项

完成了两个

但是如果子类对调度代码不可见,则会导致运行时错误:

RuntimeBinderException

类型“object”不能用作泛型类型或方法“DomainEventDispatcher.Publish(TEvent)”中的类型参数“TEvent”

这是一个人为的例子;一个更现实的事件是另一个集会内部的事件。

如何防止此运行时异常?如果这不可行,我怎样才能在Subscribe方法中检测到这种情况并快速失败?

编辑:消除动态转换的解决方案是可以接受的,只要它们不需要知道所有子类的访问者样式类。

0 投票
0 回答
351 浏览

swift - 快速双重分派数字类型

像许多人一样,我正在尝试使用整数和浮点以及这些类型的集合。

然而 Swift 类型系统并不总是那么容易被原谅。大多数人定义了一个数字协议来处理这个问题。我想知道是否有更好的方法以及Apple如何做到这一点。

所以:

Swift 中的整数有几种类型

我们可以确认他们的类型

对相同类型的 int 进行算术运算效果很好。

  1. 如果类型不同,它可能会或可能不会起作用。 2. 如果其中一种类型是 Int,则操作有效,并返回将保存结果的最小类型。
  2. 更改 i1、i2 和 i3 的值以查看此内容。注意:溢出时会发生运行时错误。

例如减法(注意这里 lhs 和 rhs 的顺序很重要)

检查类型表明确实返回了最小的 Int 。

间奏曲:Apple 如何实现这一点?他们是否将所有内容都转换为 Int,进行操作然后进行强制转换?他们如何确定最小的类型? 见马丁的评论

如果我们需要这些 Int 的集合,我们就会遇到麻烦。

此时我们搜索stackoverflow并决定使用DataType协议。

这将允许我们拥有一个数组,

如果我们明确指定元素类型。

现在我们要计算一些东西 var total : DataType = 0

不确定 _ 是或应该或可能是什么。那么这个呢?

好的,所以我们为两个 DataTypes 重载函数

经过一番搜索,我们发现了双重调度。通过双重分派,我们可以使类型更加具体。

为此,我们首先扩展 Int。

现在我们可以安全地实现我们的全局函数了

并定义我们的协议

然而,现在我们必须为符合 DataType 的每个可能的类型添加一个函数到协议中。我们还必须为符合 DataType 的每种类型实现所有这些功能。

此外,我们不能使用泛型,因为这会再次导致递归。类型没有改变。

如果我们有两个恰好有 DataType 签名的常规 Int:

即使内置函数更有效,也将使用双重调度。毕竟这会跳过两个函数调用。

所以我的问题,除了那些来自间奏曲的问题,是这样的:有没有更好的方法来完成这个?一个不需要臃肿的协议(每个支持的类型的函数)并且不会不必要地回避内置的 swift 函数。

Apple 是否使用双重调度来添加 Int 和 Int16 值(见上文)?

edit1添加了 linethrough 的(见 Martin 的评论)

edit2 Swift 有一个继承自 _IntegerArithmatic 的 IntegerArithmatic 协议。

_IntegerArithmatic 定义了不应直接使用的此类函数,因为它们是实现细节(参见头文件)。

然而 FloatingPoint 协议没有这样的区别,'isEqual' 和 '==' 函数都直接在 FloatingPoint 协议中声明。为什么有区别?

0 投票
1 回答
284 浏览

java - 具有接受 Object 类的方法时的双重调度

我有一个 Mapper 类的实现,它接受 Object 作为其中一个map(Object object)函数的参数。其余map(T t)函数接受整数或类等。

当我尝试传递一个 int 时,它会自动装箱为 Integer 并调用map(Object object)而不是map(Integer integer).

我对 Double Dispatch 做了一些研究,发现我可以使用访客模式。但这不适用于我的情况,因为我没有传递可以让它们实现接口的自定义对象accept()

上述方法接受每个对象。

当您有一个也接受 Object 的方法时,是否有针对 Java 对象进行双重调度的解决方案?

对这些 map() 函数的调用如下:foo(Object object) { mapper.map(object); }这导致map(Object object)被调用。

0 投票
0 回答
235 浏览

c# - 是否有相当于将 C# 强制转换为动态类型的 C++/CLI?

我正在扩展用 C# 编写的类层次结构,该层次结构使用 dynamic 关键字实现访问者模式(双分派),如此所述。

这是我目前在 C# 中所做的一些非常简化的伪代码:

现在,当我扩展层次结构时,派生类可能需要处理Command基类不知道的新特化。在这种情况下,双重调度将失败(似乎动态重载决议在尝试匹配方法时不会遍历扩展的类层次结构)。有一个简单的解决方法(在之前链接的文章中描述),它包括覆盖AcceptCommand()派生类上的方法(复制原始实现),如下所示:

现在,为了方便起见,最近我需要使用 C++/CLI 实现的项目中的类来扩展层次结构(与非托管 WIN32 API 代码进行大量交互)。这个项目引入了几个Command专业化,所以我需要AcceptCommand()像在 C# 中一样覆盖 C++/CLI 类中的方法以修复双重调度,但问题是我不知道如何执行Command对象的强制转换为C++/CLI 语法中的动态类型。这有可能吗?

0 投票
1 回答
115 浏览

java - 为什么Java双重调度不会导致无限循环?

在讲座中,我们看到了这段代码,并告诉我们它创建了双重调度,但为什么它没有创建一个无限循环?

如果 c3po.greet(c4po); 从 TranslationRobot 调用 TranslationRobot 方法

为什么 c5po.greet(c4po); 调用 CarrierRobot 中的 AbstractRobot 方法而不是 TranslationRobot 方法,然后不调用 TranslationRobot 中的 AbstractRobot 方法,然后调用 CarrierRobot 中的 Abstract 方法等等?

是什么决定了它是否调用 AbstractRobot 方法?

抽象机器人.java

CarrierRobot.Java

翻译机器人.Java

调度世界.Java

这将产生输出:

0 投票
2 回答
684 浏览

c++ - 混合双重调度和静态多态性

我敢肯定这是个坏主意。让我们假装我有充分的理由这样做。我有一棵成功使用静态多态性传递消息的节点树。至关重要的是,每个节点不能知道它连接的节点的类型,它只知道它传递的消息的类型。为了遍历树,我使用 CRTP 实现了访问者模式。这适用于树的第一级。

但是,当遍历到树的第二层时,下一个节点的类型将使用下面的 AnyNode 类擦除。我一直无法弄清楚如何从擦除类型向下转换为具体类型。下面的示例在测试中有效,但我认为它也可能非常危险,只是靠碰巧布置内存的地方工作。

我必须删除 中的访问者类型似乎有问题,AnyNode::Model<T>::acceptDispatch这在 中是完全已知的AnyNode::Concept::accept。但我不知道如何从概念向下转换到概念中的模型我尝试了协变虚cast函数,但没有奏效)。而且我无法使用虚拟方法将类型化的访问者传递给派生的模型类,因为无法对虚拟方法进行模板化。

有没有一种安全的方式来调用node.accept和传递访问者而不必删除访问者的类型然后将其静态转换回来?有什么方法可以Model<T>在运行时将概念向下转换为 a 吗?有没有更好的方法来解决这个问题?是不是有一些疯狂的 C++11 新方法可以解决这个问题,可能是 SFINAE?

编辑这里是访问者基类,以及派生访问者的示例。派生的访问者由客户端代码实现(这是库的一部分),因此基类无法知道将实现什么访问者。恐怕这会分散中心问题的注意力,但希望它有助于解释这个问题。此处的所有内容都有效,除非->accept( visitor )outlet_visitor::operator().

0 投票
1 回答
165 浏览

c++ - 如何使用多态参数动态调用函数

我怎样才能动态地调用表单的函数:childA.function(childB)而它们的静态类型都是父母?

并提供更多详细信息:

我有一个物理项目,我需要计算 2 个分子的势能。但是我有两种类型的分子,LC 和 Col,每种类型都有自己的参数和东西,但是我希望能够动态地调用每个分子的潜力。

所以我尝试了这个:

但是我得到了 4 的结果,因为事实证明该函数是静态调用的,这意味着由于 mol1 的静态类型是 Molecule,所以调用的函数是:

并不是

无论如何在不使用 typeid 的情况下动态调用函数(在 OOP 设计中)?

完整答案:

在 Peter 的建议下进行调查后,这被证明是经典的双重调度问题,完整的解决方案就是在虚拟内部调用另一个虚拟,如下所示:

这确实根据需要返回 3 。

0 投票
1 回答
53 浏览

java - 下面的程序可以被认为是双重调度的例子吗?

上述程序的输出是:

在市场上搜索产品。

在商店中搜索手机。

因此,输出暗示调用 market.buy(new Product()); 和 shop.buy(new Mobile()); 由调用它的对象的引用和传递给它的参数来解决。所以如果它同时使用这两个东西来调度一个函数调用,我们可以称之为双重调度吗?还是我误解了双重派遣一词?

0 投票
2 回答
590 浏览

c++ - 访问者和双重分派而不覆盖 C++ 中的“接受”方法

好的:这是我的问题:我有一个基础合成类,它接受一个访问者,然后迭代它的节点。奇迹般有效。但是,我必须使用从这个合成派生的,并认识到我必须重写派生类中的“accept()”方法才能进行正确的双重调度(我不明白)。

这带来了两个缺陷:第一,我必须打破基础的隐藏结构,第二,我必须重复代码。为了清楚起见,这是我的伪代码:

有什么优雅的解决方案吗?谢谢 !

编辑:将“virtual”添加到“accept()”以使其更精确......

0 投票
1 回答
763 浏览

c++ - 为什么我们在访问者模式中需要 accept() 以及为什么我们不能直接调用 visitor.visit()?

我正在修改前一段时间使用的访客模式。我们有一个基类 Element,它有虚方法 accept(Visitor) 并且这个方法在所有继承自 Element 的类中被覆盖。在任何派生类中,accept() 所做的只是调用visitor->visit(*this)。现在,当客户端运行代码时,他/她会执行以下操作:

为什么客户不能像这样调用visitor->visit(element):

调用 element.accept(visitor) 后又调用 visitor.visit(element) 有哪些有用的信息?这使得访问者模式的使用变得繁琐,并且在元素类的所有层次结构中都需要额外的代码。

那么有人可以在这里解释 accept() 的好处吗?