Как да напиша doubledispatch за метода за създаване на екземпляр?

метод за създаване на екземпляр, като

ClassName new

За помощ с някои подробности,

можем да напишем = аритметичен метод в абстрактен клас,

след това ги изпратете двойно в подкласове.

можем ли да използваме това при създаването на инстанция?

Пробвах с нови, но се провали. Води до някакъв предварително дефиниран основен нов метод.


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 е добре всеки нов да изпраща инициализация, така че би било basicNew инициализация. - person aka.nice; 21.06.2013

... или можете да направите нещо като:

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

което в общи линии е същата идея, но без ако :)

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. Обърнете внимание, че имаме достатъчно информация, за да можем да направим пряк път второто + извикване,

Това, което показва примерът, е, че по време на първото извикване, динамичното разрешаване на съобщения намира метод (така че дефинира като динамичен случай) и след това чрез размяна на аргумента и приемника, динамичното разрешаване на съобщения изпълнява друг случай въз основа на аргумента. Така че в края получавате метод, избран с помощта на двата обекта на първоначалното извикване. Сега относно въпроса ви: В клас Pharo съобщенията се търсят динамично, така че можете да приложите методи за създаване на екземпляри, като използвате двойно изпращане без проблем, но целта е неясна.

MyClass class>>newWith: arg
   arg newFromMyClass: aClass
person Stephane Ducasse    schedule 29.06.2013