Как вы считаете, когда вызывается статическая инициализация класса в as3? Правильно, при первом обращении к классу, его свойствам, методам и т.д. А что на счет констант? Рассмотрим пример.
Пусть у нас есть класс D , содержащий статическую константу PI и статический конструктор, выводящий в консоль текст «Static int»:
1 2 3 4 5 6 7 8 9 10 11 |
package { public class D { { trace("Static init"); } public static const PI :String = "3.14"; } } |
Для теста просто распечатываем значение константы в консоль:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package { import flash.display.Sprite; public class Test extends Sprite { public function Test() { super(); trace(D.PI); } } } |
После запуска я вижу:
1 |
3.14 |
А мой коллега:
1 2 |
Static init 3.14 |
В чем же дело? А дело в том, что мы используем разные компиляторы. Получается, что компилятор AIR SDK при обращении к константам класса не вызывает статический инициализатор (при обращении к свойствам или методам — вызывает), но если скомпилировать флешку с помощью Flex SDK, то статический инициализатор вызывается.
Почему так происходит можно наглядно продемонстрировать посмотрев набор инструкций конструктора декомпилированной флешки.
При компиляции новой версией компилятора, которая используется в AIR SDK мы получаем
1 2 3 4 5 6 7 |
constructsuper 0 getlex Qname(PackageNamespace(""),"trace") getglobalscope debugline 18 pushstring "3.14" call 1 returnvoid |
А вот SWF, скомпилированный с помощью Flex SDK
1 2 3 4 5 6 7 8 9 10 |
constructsuper 0 debugline 18 findpropstrict Qname(PackageNamespace(""),"trace") findpropstrict Qname(PackageNamespace(""),"D") getproperty Qname(PackageNamespace(""),"D") getproperty Qname(PackageNamespace(""),"PI") callproperty Qname(PackageNamespace(""),"trace") 1 pop debugline 20 returnvoid |
И так, в первом случае вызов константы заменяется на использование её значения, без обращения к классу.
Оказывается надо внимательно читать документацию:
ASC 2.0
Улучшение расчета констант
Теперь большинство констант рассчитываются на этапе компиляции. Это может изменить порядок инициализации классов. Так как ссылки на статические константы могут быть заменены рассчитанными значениями констант, MyClass.SOME_CONSTANT может не вызвать статическую инициализацию класса MyClass.
https://helpx.adobe.com/flash-builder/actionscript-compiler-backward-compatibility.html
Именно это мы и видим в декомпилированном flash файле.
В итоге. Радует, что новый компилятор исключает множество лишних инструкций и тем самым должен ускорить выполнение кода. Но реализованная в данном случае оптимизация вызывает вопросы: я считаю, что обращение к константе класса должно инициализировать класс, на этом может быть завязана определенная логика. Ну и еще раз убеждаемся, что программировать на ActionScript 3 надо с осторожностью.