2

实例创建方法,例如

ClassName new

为了帮助提供一些细节,

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

然后将它们分派到子类中。

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

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

4

3 回答 3

6

Double Dispatch在这种情况下真的没有意义new。双重分派背后的想法是,您无法通过仅分派给接收者来确定正确的行为。(单个)参数的类型对选择(分派)的行为具有相同的影响。换句话说,只有当你的方法有参数时,双重分派才有意义,new因为它是一元的,它没有。

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

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

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

于 2013-06-20T21:41:02.910 回答
4

...或者您可以执行以下操作:

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

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

于 2013-06-21T09:45:45.460 回答
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
于 2013-06-29T14:10:10.777 回答