Как написать даблдиспатч для метода создания экземпляра?

метод создания экземпляра, например

ClassName new

Чтобы помочь с некоторыми деталями,

мы могли бы написать a = арифметический метод в абстрактном классе,

затем дважды отправьте их в подклассы.

Можем ли мы использовать это при создании экземпляра?

Я пробовал новый, но он терпит неудачу. Приводит к некоторому заранее определенному базовому новому методу.


person marsrover    schedule 20.06.2013    source источник


Ответы (3)


Double Dispatch не имеет смысла в случае new. Идея двойной отправки заключается в том, что вы не можете определить правильное поведение, отправляя только получателю. Тип (одиночного) аргумента оказывает одинаковое влияние на то, какое поведение выбирается (отправляется). Другими словами, двойная отправка имеет смысл только в том случае, если у вас есть аргументы для ваших методов, а new, будучи унарным, не имеет смысла.

Тем не менее, вы, безусловно, можете реализовать свой собственный метод new, который переопределяет унаследованный метод по умолчанию. И вы можете заставить его делать все виды интересных вещей. Обычно выполняется некоторая проверка среды, чтобы определить, какой подкласс подходит.

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

Обратите внимание, что здесь мы используем basicNew, а не new. Если бы вы использовали new, вам нужно было бы либо реализовать отдельные переопределения в этих подклассах, иначе он просто унаследовал бы и повторно отправил сообщение AbstractClass>>>new.

person Travis Griggs    schedule 20.06.2013
comment
Как отметил Эстебан, в версии Squeak/Pharo хорошо себя вести, когда каждая новая отправка инициализируется, поэтому это будет базовая инициализация New. - person aka.nice; 21.06.2013

... или вы можете сделать что-то вроде:

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

что в основном та же идея, но без ifs :)

person EstebanLM    schedule 21.06.2013

Ключевым моментом двойной отправки является то, что, поменяв местами получателя и аргумент основного сообщения, вы вызываете второй раз виртуальный вызов и получаете эффект выбора метода на основе получателя сообщения и его аргумента. Поэтому вам нужно иметь сообщение с аргументом.

Вот типичный пример двойной отправки: сложение целого числа и числа с плавающей запятой и выполнение адекватного преобразования.

 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
person Stephane Ducasse    schedule 29.06.2013