Macromedia Flash 5. Объектно - ориентированное программирование

       

Super - запуск конструкторов


После функции extends, использовать конструктор - как два байта переслать. Главное сделать следующее: передать аргументы конструкторам, которым они нужны, а затем запустить конструкторы в порядке сверху вниз по списку. Единственное, о чём нужно помнить, это то, что конструкторы по своей сущности не связаны друг с другом, в отличие, например, от прототипов. Так что нам придётся "взбираться" вверх по цепочке прототипов и на каждом уровне "возвращаться" назад к конструктору.

Как я уже говорил раньше, иногда полезно посмотреть на работу других объектно-ориентированных языков программирования, чтобы сравнить, "как там у них". JAVA использует ключевое слово super, которое выполняет в точности то, что нам сейчас нужно, и даже кое-что ещё. Так что думаю, оно заслуживает более детального рассмотрения. В JAVA ключевое слово 'super' используется для вызова конструктора родительного класса - если нужно, то вместе с аргументами. Для этого используется следующий синтаксис: super(arg0, arg1, ...). Есть одно ограничение, эта строка должна стоять самой первой в каждом конструкторе. Если где-то она пропущена, то по умолчанию автоматически принимается она же, но без аргументов. Вместо того, чтобы удалить себя, после того, как действие всех конструкторов истекло, её "жизнь" продолжается, теперь это указатель на родительский класс, что позволяет экземплярам вызывать перезаписанные методы с помощью выражения super.xxx( ).

Наше преимущество в том, что в ActionScript мы обладаем всеми функциями, которые выполняет ключевое слово super в JAVA. Возможно, мы немного озадачиваем пользователя двумя маленькими действиями (может ему и трудно, но нам-то какая разница!) Первое, вам необходимо использовать выражение this.super( ), а не просто super( ). Экземпляры просто обожают слово "this", когда о себе "рассказывают" в пределах обычной программы. Я бы сказал, им это нравится (здесь мне вспоминается одна фраза Оскара Уайлда: "Но довольно об этом. Что вы думаете обо мне?") В нашем случае они "разговаривают" о своей "сверх"-миссии. Так что придётся всё-таки писать this.super. Привыкайте! Смотрите на это, как на дополнительную функцию. Если бы не ключевое слово this, то процедура "super" в ActionScript была бы настолько похожа на аналогичную процедуру в JAVA, что пользователи стали бы забываться, а кое-кто и биться головой о стену.


Теперь о втором "усложнении". Пользователь ДОЛЖЕН ставить this.super( ... ) первой строкой любого конструктора. Никакого волшебства. Есть много способов проверить, есть ли у того или иного конструктора вызов super или нет и, в случае, если такового не наблюдается, вставить его. К сожалению, нам никак не обойтись без того, чтобы запустить этот конструктор, а в некоторых случаях это может привести к отклонению от нужного нам курса - представьте себе, что мы ввели новую статичную переменную, следящую за тем, сколько всего экземпляров было создано. Ну да ладно, мы ещё поквитаемся! Теперь необходимо, чтобы пользователь вставлял выражение this.super( ) первой строкой каждого конструктора. Вы спросите: "возникнет ли ошибка, если мы не станем этого делать?" (подобно тому, как это организовано в JAVA) Ну что тут скажешь! Работа с многоцелевыми библиотеками ActionScript требует жертв.

Итак, перейдём к самому процессу. Сначала передаём аргументы вверх по цепи конструктора, а затем запускаем конструкторы в порядке сверху вниз. После этого super немного изменяется. Теперь выражение выглядит так - parent.prototype, совсем как в JAVA, так что у вас есть доступ к перезаписанному свойству или методу посредством использования выражение this.super.xxx( ). Проверьте, понимаете ли вы всё что происходит в этой цепи. (Я - почти понимаю, но ведь это всё я написал...) (В будущем: я должен объяснить это немного лучше :) ).

// SUPER ---------------------- Object.customKeyword.prototype.super = function() { // this.super(); должно стоять первой строкой всех конструкторов

// счётчик get chain - сообщает нам (по мере продвижения вверх // по цепочке конструкторов), сколько раз был // вызван super с тех пор, как был создан новый пример // Это также увеличивает счётчик.

var count = Object.customKeyword.prototype.super.prototype.cnt++;

// находим следующий конструктор var fn = this.__proto__.__proto__; while(count-- > 0) { fn = fn.__proto__; } fn = fn.constructor;

// вызываем этот конструктор в экземпляр, передаём аргументы this.$_base = fn; this.$_base( arguments[0],arguments[1], arguments[2],arguments[3], arguments[4],arguments[5], arguments[6],arguments[7] ); delete this.$_base;

// проверяем, действительно ли мы в начале цепи if(fn.prototype.__proto__ == Object.customKeyword.prototype) { // если да, перезаписываем значение super // для этого экземпляра, // теперь super указывает на родительный прототип, // таким образом можно вызвать перезагруженные // функции и вернуть их аргументы this.super = this.__proto__.__proto__.prototype; // обнуляем счётчик цепи для следующего экземпляра Object.customKeyword.prototype.super.prototype.cnt = 0; } } Object.customKeyword.prototype.super.prototype.cnt = 0;

<<

   ООП во Flash 5    >>


Содержание раздела