понедельник, 31 января 2011 г.

Протохаки

Последнее время по работе активно осваивал JS. И в процессе отходняка от взлома мозга и взрыва всех основательно прикипевших принципов ООП стали появляться вопросы.

Вопрос: вот есть AS3, он же вроде причёсанный Adobe'ом форк JS, а в основе JS лежит концепция prototype(а это клёвая штука! :)), а куда она делась в AS3? [Тут надо заметить, что AS2\1 я вообще знать не знаю и в глаза не видел].

Потом у меня образовался непредвиденный отпуск, и я от нечего делать начал ковыряться с Burrito-Hero-Android-iPhone и другими новоявленными интересностями во флеше.

Пишу я значит аппликуху, пишу, и тут натыкаюсь на задачу: хочется мне расширить класс Array нужным мне методом.

ООП-way: "наследуйся!".
JS-way:
Array.prototype.newMethod =
function() {blah-blah};



Вспоминаю свой Вопрос, гуглю - оказывается никуда ничего не делось, всё на месте, но нужно учитывать специфику. [А в AS2/1 так вообще, оказывается, прототипирование пышны м цветом цвело.]

Почитал, порадовался. Но. Adob'овцы настоятельно не советуют. Мол ООП наше всё и нефиг искать лёгких путей. Кроме того куча ограничений портящих всю малину. Более менее удобно prototype использовать для динамических классов:

var arr:Array = [1,2,3];
arr.checksumm();
или сразу [1,2,3].checksumm();
удобно?

Для не динамических классов, чтобы прорваться через компилятор приходится разыменовываться к Object, что уже съедает весь профит. Хотя нетипизированные переменные частично решают проблему:

var a = 5;
a.minutes().ago(); // вернёт время(Date) на a минут меньшее, чем
now
красиво?

А вот вариант когда использование prototype может быть реально полезно:
возвращаемся к нашему Array, которому хочется добавить метод. Не выёживаемся и идём ООП путём. А теперь начинаем оптимизировать, и приходим к выводу что надо бы вместо Array сделать Vector.<int> и сильно огорчаемся, узнав что от Vector.<*> отнаследоваться никак нельзя, final класс, все дела. Можно мутить врапперы-хелперы, а можно воткнуть метод через prototype и использовать так:

var b:Vector.<int> = new Vector.<int>();
b.push(1,2,3);
trace(Object(b).sum()); // =6!

профит!
Если кому интересно могу опубликовать здесь исходники, но вообще тут довольно внятно всё объясняется.