Несколько раз в форумах посвященным разным языкам я видел вопросы о наличии метода "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-е".
Ярлыки: vw