Тонкости и трюки ActionScript`а, которые... бесполезны
Есть такие вещи в ActionScript`е, которые в нормальных ситуациях просто неприменимы. Я даже скажу иначе: те, которые сложно применить даже в наркотическом опьянении.
Весь код, написанный на ActionScript`е при компиляции превращается в байт-код: последовательность команд, которую исполняет виртуальная машина Tamarin, встроенная в Flash Player. Эти последовательности команд выполняются линейно. Небольшая проблема встречается в том, что код, который мы пишем чаще всего нелинейный: в нём очень много ветвлений — условия, циклы. Собственно, в теории трансляции языков данная проблема решается очень просто: код "развертывается" в набор линейных команд, а все эти ветвления реализуются в виде условных переходов на необходимый участок кода. Проще говоря, при исполнении код "скачет" по линейному набору разных команд. Что я хочу сказать?
Я хочу сказать, что при исполнении этот код частенько не подвергается разным проверкам на валидность. Чаще всего подобные проверки делает компилятор. Поэтому имея в руках спецификацию формата и какой-нибудь редактор байт-кода (даже HEX-редактор подойдёт) мы можем творить несусветную вакханалию... которая будет валидной.
Но нет, сегодня мы не будем уходить за рамки того, что можно скомпилировать из чистого AS3.
1) Множественный вызов... конструктора?
Наш участник BlooDHounD ещё давно писал статью о том, что можно обмануть компилятор и не вызвать конструктор суперкласса... никогда. Например, вот так:
super() никогда не вызовется. Это приводит нас к мысли о том, что в коде всего-лишь должен появится super(), а где — не важно.
Создадим класс SuperClass, в конструкторе которого напишем, например: после создадим класс Descendant, который будет наследоваться от SuperClass (Descendant extends SuperClass).
В конструкторе Descendant напишем следующее:
И да. Мы увидим в панеле output "Hello from superclass!" 10 раз.
2) Обращение к методам суперкласса до его инстантиации.
Меня всегда смущало, что я не могу писать вот так:
Конечно, по логике то что я пишу в принципе не может быть верным. Но смущение наступает, когда следующий код признается валидным и валидно исполняется:
Что это значит? Это значит что вовсе необязательно дёргать super() перед тем, как обратиться к методу суперкласса. Но, предположим, тот же addEventListener переопределен в текущем классе, а нам нужно обратиться к addEventListener именно суперкласса до вызова его конструктора. Что делать? Нужно всего лишь вынести это обращение в другой метод. Компилятор не будет копать так глубоко, а интерпретатору, честно говоря, пофиг.
public function Constructor(){ someMethod(); super(); } private function someMethod():void{ super.addEventListener(...); }
Это нельзя отнести к глупостям или странностям, но меня это забавляет.
Вот такой вот метод:
позволит достать из класса всё что угодно. Однако, что радует, приватные поля суперкласса таким образом заполучить не удастся.
4) Нет уверенности в завтрашнем дне, мы меняем константу.
Константы это то, что нельзя изменить. Важно понимать разницу между изменить и "залезть внутрь".
Например, массив-константа:
может наполняться содержимым с помощью метода push класса Array, но не может быть заменен другим массивом. (я не могу написать ARRAY=[1,2,3]).
Теперь давайте объявим не-статическую константу:
Попробовав её изменить мы получим ошибку компиляции. Это нормально. Но давайте не забывать о том, что у нас есть динамический доступ: меняем константу вот так:
и... вуаля.
Но, что странно, если константа помечена как static — во время её изменения мы, слава богу, получим RTE.
5) Интересный интеллект компилятора
Я не знаю, как назвать этот пункт. Наверное, ни для кого не секрет, что FlexSDK как компилятор имеет достаточно низкий порог оптимизаций: во время компиляций он не складывает даже константы!
Вот такой вот код:
попадет в байт-код именно как 5+5+10. Хотя, хотелось бы, чтобы он попал туда как 20.
Но... услужливый компилятор скажет, что через ссылку на класс, которую я присвою в рантайме идёт динамическое обращение к константе (!!!).
Между слов, проще выразить это в коде (Класс Main):
private static const obj:String="5"; ... var cl:Class = Main; var cl2:Class = cl; cl2.obj = "30";
Офигеть.
Всего комментариев 25
Комментарии
![]() ![]() |
|
Про множественный вызов суперконструктора прикольно. Копай ещё.
А отмена инкапсуляции похожа на антипаттерн Public Morozov |
![]() ![]() |
|
про константу и Array не в тему. это абсолютно нормальное поведение. свойства массива же не помечены как константа.
|
![]() ![]() |
|
Вроде про Array сказано так, к слову. А вот константа как раз помечена как константа, но ее можно изменить через this[] — не особо как-то нормально.
|
![]() ![]() |
|
![]() ![]() |
|
это косяки последнего компилятора. раньше он палил это. сейчас dynamic перестал быть стронг кейворд.
|
![]() ![]() |
|
Я что-то последний пример не пойму - это типа тоже 'косяки компилятора/интерпретатора'??
|
![]() ![]() |
|
![]() ![]() |
|
Нет, сказали же, это тупо баг компилятора )
|
![]() ![]() |
|
Цитата:
Отмена инкапсуляции.
|
|
Обновил(-а) alatar 11.05.2011 в 01:28
|
![]() ![]() |
|
Ну как бы это пост и не претендовал на открытие Истины.
2 alatar. на самом деле это не совсем павлик морозов, ибо родительское приватное он всё-таки отдать не может, только протектед, поэтому полностью реализовать Public Morozov в AS3, к счастью, не получится. |
|
Обновил(-а) Котяра 11.05.2011 в 17:57
|
![]() ![]() |
|
2 Котяра, я об этом и говорил. Нет там никакой отмены инкапсуляции. Абсолютно логичное и ожидаемое поведение. В полном соответствии с ООП.
|
![]() ![]() |
|
Тебе конкретно название не нравится?
|
![]() ![]() |
|
Аха
![]() |
![]() ![]() |
|
Предложи своё название для этого трюка )
|
![]() ![]() |
|
ООП
![]() |
![]() ![]() |
|
Цитата:
И вытворял он эти трюки, пока не стал страдать тонкостью
|
![]() ![]() |
|
множественный вызов конструктора это просто класс - не знаю где это можно применить, но на заметку возьму :-) Спасибо за подборку, восхитило!
|
![]() ![]() |
|
![]() ![]() |
|
про тип это очепятка
|
![]() ![]() |
|
По разному можно, не считаю за суть )
П.с. Первый пост на флешер с айфони |
Последние записи от Psycho Tiger
- Тонкости и трюки ActionScript`а, которые... бесполезны (10.05.2011)
- Vkontakte: как пользоваться wall.post, нужен ли теперь wall.savePost? (05.03.2011)
- А пятый контер-страйк хорош. (19.01.2011)
- Пацаны, гоу Вконтакте? (21.12.2010)
- Давайте начистоту (18.12.2010)