PDA

Просмотр полной версии : Беседа о нативном итераторе for in


Psycho Tiger
28.02.2011, 23:47
Всем привет! Заболтали мы тут с cleptoman`ом о тщетности всего сущего и задумались вот над чем.
Есть у нас итератор for in. Замечательный, кстати! Но в хэлпе черным по белому сказано, что ключи должны быть String
for (var name:String in object) {
}
Ну здорово. А ещё у нас есть такой класс-коллекция Dictionary, в него в качестве ключей можно совать даже не String`и.
var timer:Timer=new Timer(1000);
var hash:Dictionary=new Dictionary();
hash[timer]="bingo!";
for (var name:String in hash){
trace(hash[name]); //undefined
}
Почему? Ну, все дружно скажут: "потому что name это Timer, а мы идём по String`ам". А сможете так же дружно ответить, почему же если мы "итерируем" по String то всё равно вошли в выполнение блока кода внутри итератора?
На самом деле оказалось, что этот засранец всеми силами пытается сделать из ключа String. Например, функцией String или методом toString, но это, по-сути, одно и то же.
А ещё мы знаем о том, что в качестве ключа мы можем использовать Object. Этакая недокументированная фича. Во всяком случае, я сейчас говорю так: ранее я думал чуть иначе. Например, ожидая DisplayObject мы можем передать MovieClip. Такой подход называется сужением — сузили функционал MovieClip до DisplayObject. И вот когда я не думал об этом, я думал что аналогичный функционал работает и там: просто передали Object (ведь String extends Object), далее происходит конвертирование объекта в Object (как ранее в String) и всё хорошо.
Но нет, ошибка. Мне поначалу было трудно её осмыслить (почему — не знаю). Приведу на примере:
SimpleButton extends DisplayObject (в конечном итоге).
String extends Object.
Ожидая SimpleButton мы НЕ можем передать DisplayObject.
Ожидая String мы НЕ можем передать Object.

Но передаем ведь... а как? А так сложилось, что Object это базовый тип во флеше вообще. Причем он динамический. Проще говоря, допустимо читать Object как "нетипизирован". Но есть и другая форма записи "нетпизировано" — это :*. И это нормально работает в качестве типа ключа для for-in.

Ну что здесь сказать, много написано, а в принципе ни о чем. Захотелось поделиться, почему-то, а в блог такую чушь постить стыдно.
Мои домыслы в том, что for-in для name:String и name:Object — это разные итераторы.

expl
28.02.2011, 23:59
Ни что не идеально в этом мире, даже на солнце есть пятна

dimarik
01.03.2011, 00:10
Напомните, итерировать Dictionary нельзя?

Добавлено через 19 минут
Например, ожидая DisplayObject мы можем передать MovieClip. Такой подход называется сужением — сузили функционал MovieClip до DisplayObject.

Это классический случай восходящего приведения.

Psycho Tiger
01.03.2011, 00:50
Напомните, итерировать Dictionary нельзя?
Можно, почему нет?
Это классический случай восходящего приведения.
Даже так )

expl
01.03.2011, 00:55
Напомните, итерировать Dictionary нельзя?
Хоть тут вроде как и написано, продублирую в коде, на всякий случай:

for (var key:* in dictionary)
{
var typedKey:MyKeyType = key;
var value:MyType = dictionary[typedKey];//или dictionary[key];
}
// Если ключ не нужен:
for each (var value:MyType in dictionary)
{
//...
}

cleptoman
01.03.2011, 08:56
да, с * или Object в качестве типа ключа все хорошо..но если поставить реальный тип ключа - RTE с тем что он не может String (!откуда он вообще тут??)сконвертить в нужный тип.

Psycho Tiger
01.03.2011, 17:32
Не RTE, а ошибка компиляции.

cleptoman
01.03.2011, 18:08
ну да

dimarik
01.03.2011, 21:20
Честно скажу, что Dictionary никогда не использовал в своих разработках. Скорее всего даже возникла антипатия на почве массового быдлокода с использованием Dictionary. Хотя, как инструмент, наверняка он может быть где-нибудь полезен. Спасибо за примеры ).

Psycho Tiger
01.03.2011, 21:55
А как ты делал, когда тебе надо было перебросить какое-нибудь значение с объектом? (ну, например внутрифизический id экземпляра кнопки при клике, если обработчик для кучи кнопок один)? Создавал наследника или проверял в цикле на все возможные значения? Последний вариант куда более быдлокодерский.

dimarik
01.03.2011, 22:07
Вероятно, я не до конца понял суть вопроса.

function обработчик(event:Event):void {
if (event.eventPhase !== EventPhase.AT_TARGET) return;
trace( (event.target as МояКнопка).внутрифизический_id);
}

Psycho Tiger
01.03.2011, 22:45
Понятно.
Лично у меня достаточно часто дизайн уже собран и мне приходится доставать SimpleButton по getChildByName. У меня нет возможности привести SimpleButton к CustomSimpleButton (во всяком случае не создавая обёрток и прочего, что в 9 из 10 случаев излишне), поэтому Dictionary для меня панацея.

dimarik
01.03.2011, 22:52
Подмени классы кнопок в рантайме. Делов-то! )

Psycho Tiger
01.03.2011, 22:58
Это не проблема )
Просто я же говорю, в 9 из 10 случаев SimpleButton справляется лучше некуда. Незачем жирафу когти растить )

expl
01.03.2011, 23:00
Честно скажу, что Dictionary никогда не использовал в своих разработках.
Опаньки, а как Вы искали вьюшку по ее модельке?
Или один я, идиот, так делаю, а есть какой-то более прозрачный и "правильный" способ?

dimarik
02.03.2011, 00:06
Это не проблема )
Просто я же говорю, в 9 из 10 случаев SimpleButton справляется лучше некуда. Незачем жирафу когти растить )
А как тебе другие варианты идентификации кнопок?

private var _buttonIndex: uint;

function обработчик(event:Event):void {
if (event.eventPhase !== EventPhase.AT_TARGET) return;
const button:InteractiveObject = event.target as SimpleButton;

if (button.tabIndex == 0)
button.tabIndex = ++this._buttonIndex;

trace( button.tabIndex /* as внутрифизический_id */ );
}

либо


private var _buttonIndex: uint;

function обработчик(event:Event):void {
if (event.eventPhase !== EventPhase.AT_TARGET) return;
const button:DisplayObject = event.target as SimpleButton;

if (button.name.indexOf('instance') != -1)
button.name = uint(++this._buttonIndex).toString(33);

trace( button.name /* as внутрифизический_id */ );
}

Тигра, у тебя есть более весомые доводы в пользу использования Dictionary?

Psycho Tiger
02.03.2011, 00:31
Димка, вот я программирование в 12 лет полюбил именно за то, что здесь можно придумать 40 разных способов реализовать задачу, один краше другого. Всякие геометрии, физики и прочее мне не нравились своей "сухостью". Ну нашли мы длину катета, ну и что? А вот когда начал серьезно увлекаться программированием появилась любовь и к геометрии, и к матану, и к физике...
Конечно, можно обходиться без Dictionary в любой ситуации. Можно даже обходится без if/switch, делая всё тернарным ?. Но стоит ли?
В твоём примере tabIndex может использоваться по назначению. К тому же он паблик. Что же это, кто-то используя мой класс и поменяв таб-индекс у кнопки поломает всю мою программу? Или мне перекрывать getChildByName, getChildAt, останавливать распространение Event.ADDED и всё такое?
Похожая ситуация и с name. Только названия мы даём более-менее осмысленные, нести какие-то метафизические свойства в нём как-то не очень.

Проще говоря, я нашел как минимум одно: здоровая инкапсуляция с отсутствием "лишних" сущностей.
А какие у тебя против?

Добавлено через 5 минут
P.S. вспомнил тут. Когда не умел делать наследования и всё такое, стояла задача передать число в обработчик. Были мысли воспользовать transfom#Matrix#a,b... — типа когда меняются всё равно ничего не происходит (я не обновлял, просто менял), а число прилетает. Вот из этой же серии.

terbooter
02.03.2011, 00:39
Ни разу в жизни не использовал Dictionary, кроме тестовых программ, для теста его же самого.
Не горжусь и не стыжусь =)

Psycho Tiger
02.03.2011, 00:44
Я ни в коем случае не пропагандирую его использование =)
Я пропагандирую отказ от плясок с бубном с целью показать, что в принципе и без него можно.

Может, дело вкуса.

terbooter
02.03.2011, 00:46
А как ты делал, когда тебе надо было перебросить какое-нибудь значение с объектом? (ну, например внутрифизический id экземпляра кнопки при клике, если обработчик для кучи кнопок один)? Создавал наследника или проверял в цикле на все возможные значения? Последний вариант куда более быдлокодерский.
Вообще, уже не здоровая ситуация, что с нажатием кнопки нужно перебрасывать куда-то какое-то значение.

Добавлено через 3 минуты
По сабжу, по-моему я как то предвзято стал относиться к использованию Dictionary после тестов подобных вашим.

Psycho Tiger
02.03.2011, 01:07
Вообще, уже не здоровая ситуация, что с нажатием кнопки нужно перебрасывать куда-то какое-то значение.
Почему же. Клик по кнопке отсылает событие вверх, например "открой большое окно". Это большое окно может иметь разный контент, пусть он базируется на каком-нибудь int`е. Один обработчик для 10 кнопок, вместе с событием протаскиваем id окна через _hash[event.target].