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

Smalltalk 如何为实例创建方法编写doubledispatch?,smalltalk,pharo,squeak,Smalltalk,Pharo,Squeak,实例创建方法,如 ClassName new 为了帮助了解一些细节 我们可以在抽象类中编写a=算术方法 然后在子类中双重分派它们 我们可以在实例创建中使用它吗 我试过新的,但失败了。导致一些预定义的基本新方法。双重分派在新建的情况下没有意义。双重分派背后的思想是,您不能仅通过分派给接收者来确定正确的行为。(单个)参数的类型对选择(调度)的行为具有相同的影响。换句话说,双分派只有在方法有参数时才有意义,new是一元的,而不是一元的 也就是说,您当然可以实现自己的new方法来覆盖股票默认继承的方法

实例创建方法,如

ClassName new
为了帮助了解一些细节

我们可以在抽象类中编写a=算术方法

然后在子类中双重分派它们

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


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

双重分派
新建
的情况下没有意义。双重分派背后的思想是,您不能仅通过分派给接收者来确定正确的行为。(单个)参数的类型对选择(调度)的行为具有相同的影响。换句话说,双分派只有在方法有参数时才有意义,
new
是一元的,而不是一元的

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

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

请注意,这里使用的是
basicNew
,而不是
new
。如果使用了
new
,则需要在这些子类中实现不同的重写,否则它只会再次继承并重新发送
AbstractClass>>new
消息。。。或者你可以这样做:

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

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

双重分派的关键点是,通过交换主要消息的接收方和参数,您可以第二次调用虚拟调用,然后您可以根据消息接收方及其参数选择方法。因此,您需要有带参数的消息

这里是一个典型的双重分派示例:加法整数和浮点,并执行适当的转换

 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

正如Esteban所指出的,在Squeak/Pharo风格中,每个新成员都发送一个initialize,这是一个很好的行为,因此它应该是basicNew initialize。
MyClass class>>newWith: arg
   arg newFromMyClass: aClass