如何为实例创建方法编写doubledispatch?

时间:2013-06-20 21:02:47

标签: smalltalk pharo squeak

实例创建方法,如

ClassName new

为了提供一些细节,

我们可以在抽象类中编写一个算术方法,

然后在子类中双重发送它们。

我们可以在实例创建中使用它吗?

我尝试了新功能,但失败了。导致一些预定义的基本新方法。

3 个答案:

答案 0 :(得分:6)

Double Dispatch案例中,

new没有任何意义。双重调度背后的想法是,您无法通过仅调度接收器来确定正确的行为。 (单个)参数的类型对选择(调度)的行为具有相同的影响。换句话说,双重调度只有在您的方法有参数时才有意义,new是一元的,而不是。

也就是说,您当然可以实现自己的new方法,该方法会覆盖库存默认继承的方法。你可以让它做各种有趣的事情。通常会进行某种环境检查以确定适合的子类。

AbstractClass>>>new
    ^self platform = #unix
        ifTrue: [SubclassThatLeveragesUnix basicNew]
        ifFalse: [CrappyPCSubclass basicNew]

请注意,我们在此使用basicNew,而不是new。如果您使用new,则需要在这些子类中实现不同的覆盖,否则它将只是继承并重新发送AbstractClass>>>new消息。

答案 1 :(得分:4)

......或者你可以这样做:

AbstractClass class>>#new 
    ^ (self platform concreteClassFor: self) basicNew initialize.

这基本上是相同的想法,但没有ifs:)

答案 2 :(得分:1)

双重调度的关键点是,通过交换接收器和主消息的参数,您第二次调用虚拟调用,然后您将获得基于消息接收器及其参数选择方法的效果。因此,您需要带有参数的消息。

以下是双重调度的典型示例:加法整数和浮点数并执行适当的转换。

 Integer>>+ arg
   ^ arg sumFromInteger: self

 Float>>+ arg
   ^ arg sumFromFloat: self

 Integer>>sumFromInteger: anInt  
   <primitive adding to ints>

 Integer>>sumFromFloat: aFloat
   ^ self asFloat + aFloat

 Float>>sumFromFloat: aFloat
   <primitive adding two floats>

 Float>>sumFromInteger: anInt
   ^ self + anInt asFloat

现在1 + 1.0将在Integer上首先击中+然后是sumFromInt:然后是+然后是sumFromFloat。请注意,我们有足够的信息,所以我们可以快捷第二个+调用,

示例显示的是,在第一次调用期间,动态消息解析在方法上找到(因此它定义为动态情况),然后通过交换参数和接收器,动态消息解析执行另一种情况,基于ARG。因此,最后您将获得使用原始调用的两个对象选择的方法。 现在关于你的问题:在Pharo类中,动态查找消息,这样你就可以使用双重调度实现实例创建方法而没有问题,但目标不明确。

MyClass class>>newWith: arg
   arg newFromMyClass: aClass