Smalltalk по-русски
среда, Сентябрь 13, 2006
[VW] super super

Несколько раз в форумах посвященным разным языкам я видел вопросы о наличии метода "super super", который позволил бы вызвать метод не в родительском классе, а у родителя родителя - "дедушки". Не будем рассказывать о том, что такое желание свидетельствует о необходимости рефакторинга, а остановимся на интересном техническом моменте озвученном Элиотом Мирандой в c.l.s.

Оказывается, что в VW есть 2 способа добится желаемого эфекта. Они, естественно "не документированные" и не должны использоваться в "обычном" коде. Первый способ - использование специализированной версии #perform::

perform: selector withArguments: anArray startingAbove: aBehavior
     "Отправляет получателю сообщение, начинает поиск метода 
      с суперкласса aBehavior. selector - селектор сообщения, 
      anArray - аргументы сообщения. Если такой селектор не найден, 
      то вызывает messageNotUnderstood:.
      aBehavior. Если aBehavior не (супер)класс объекта, или
      размер anArray не соответсвует количеству параметров искомого
      метода, то происходит ошибка примитива"

        <primitive: 515 errorCode: ec>
        ^self primitiveFailed 

Второй способ потребует изменения синтаксиса и, естественно, компилятора. Байткод VW для 'super' принимает в качестве параметра класс, с которого починается поиск метода. Например код

super printOn: aStream
обычно компилируется в
1 |44| push self
2 |10| push local 0
3 |1C| push {TheClassInWhichThisMethodIsDefined}
4 |F2 21| super send printOn:
Таким образом, используя этот байткод можно ввести, например, такой синтаксис:
self.ClassName foo
Обратите внимание, что, в отличии от примитива, байткод не проверяет, что такой класс, является суперклассом для текущего класса. Это обычно не проблема, так как в обычной ситуации в байткод проставляется класс, в котором метод и находится. Однако, если вы сами будете генерировать эти байт-коды и не обеспечите необходимой проверки. то ВМ упадёт. Для изменения компилятора можете воспользоваться подсказками из статьи "Путеводитель хич-хайкера по компилятору в Smalltalk-е".

Ярлыки:

Comments:
В Dolphin Smalltalk этого можно было бы достичь с помощью ##(super) (не нашел аналога в VW), если бы это выражение захотело компилироваться в байт-код :)

##(self) не часто, но активно использую.
 
Я не знал об этой возможности, спасибо.

Кстати, у меня даже была такая ситуация, когда надо было сделать super super - правда, в Squeak. И отрефакторить там не получалось - так как я наследовался от класса из одной библиотеки (и переопределял метод), который, в свою очередь, наследовался от класса из другой библиотеки (и тоже переопределял этот метод). В принципе, можно было бы сделать глобальный рефакторинг - но при этом терялась возможность обновлять библиотеки, чего не хотелось. В итоге, я там таки сделал то, что хотел, но довольно таки некрасиво (правда, не помню уже, как именно :-) ).

Да, кстати, в Squeak, как оказалось, тоже есть аналогичный метод:

perform: selector withArguments: argArray inSuperclass: lookupClass
"NOTE: This is just like perform:withArguments:, except that
the message lookup process begins, not with the receivers's class,
but with the supplied superclass instead. It will fail if lookupClass
cannot be found among the receiver's superclasses.
Primitive. Essential. See Object documentation whatIsAPrimitive."

<primitive: 100>
(selector isSymbol)
ifFalse: [^ self error: 'selector argument must be a Symbol'].
(selector numArgs = argArray size)
ifFalse: [^ self error: 'incorrect number of arguments'].
(self class == lookupClass or: [self class inheritsFrom: lookupClass])
ifFalse: [^ self error: 'lookupClass is not in my inheritance chain'].
self primitiveFailed
 
Отправить комментарий

<< Home

Популярные статьи
:: Smalltalk?!
:: Почему Smalltalk?
:: Great Leap Forward from Java to Smalltalk

Последние сообщения
:: [VW] Cookbook
:: [VW] Smalltalk в синтаксисе C
:: [VW] VisualWorks 7.4.1 and Object Studio 7.1.1
:: [Squeak] DrGeoII
:: [SqNOS] Прогресс
:: Smalltalk-80 в "ящике"
:: [Squeak] Одной строкой...
:: [Job] Работа в Санкт-Петербурге
:: [Seaside] Morphic в обычном броузере
:: Сборная солянка

Архив
Предыдущие новости / Декабрь 2004 / Январь 2005 / Февраль 2005 / Март 2005 / Апрель 2005 / Май 2005 / Июнь 2005 / Июль 2005 / Август 2005 / Сентябрь 2005 / Октябрь 2005 / Ноябрь 2005 / Декабрь 2005 / Январь 2006 / Февраль 2006 / Март 2006 / Апрель 2006 / Май 2006 / Июнь 2006 / Июль 2006 / Сентябрь 2006 / Октябрь 2006 / Ноябрь 2006 / Декабрь 2006 / Январь 2007 / Февраль 2007 / Март 2007 / Апрель 2007 / Май 2007 / Июнь 2007 / Август 2007 / Сентябрь 2007 / Ноябрь 2007 / Январь 2008 / Март 2008 / Май 2008 / Июнь 2008 / Июль 2008 / Август 2008 / Сентябрь 2008

Atom Feed
Smalltalk по-русски


Powered by Blogger