Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   обращение сразу ко всем экземплярам определенного класса (http://www.flasher.ru/forum/showthread.php?t=145685)

Dr_Bra 16.10.2010 15:07

обращение сразу ко всем экземплярам определенного класса
 
Всем привет!

У меня вот такой вопрос:
Можно ли, каким-то образом, обратиться сразу ко всем экземплярам определенного класса, которые отображены на сцене?

i.o. 16.10.2010 15:40

Пройтись по каждому экземпляру и проверить, является ли он наследником определенного класса, с помощью оператора is

alatar 16.10.2010 15:41

Обратиться к экземпляру класса, можно только имея ссылку на него.
Т.е. вам необходимо сделать статическое "хранилище" ссылок на экземпляры этого класса и при создании экземпляра (в конструкторе) заносить ссылку на экземпляр в хранилище. Для оптимизации и возможности удаления объектов, ссылки можно сохранять по ADDED и удалять по REMOVED.

3p.station 16.10.2010 15:48

если я правильно понял то возможно вам будет интересно посмтреть в сторону либо наблюдателя или
компоновщика

i.o. 16.10.2010 16:00

3p.station, в данной задаче это перегиб

Котяра 16.10.2010 18:25

можно
например в конструкторе регистрировать экземпляр в каком нибудь статичном массиве.
Код AS3:

package ru.k0t0vich 
{
    import flash.display.Sprite;
 
    /**
    * Регистрируемые спрайты
    * @author k0t0vich
    */

    public class RegisteredSprite extends Sprite
    {
        static private var _instanceArray:Array;
 
        public function RegisteredSprite()
        {
            super();
            // можно регистрировать в конструкоре, но можно и добавлятьудалять по событиям добавления/удаления на сцену.
            RegisteredSprite.instanceArray.push(this);
        }
 
        static public function get instanceArray():Array { 
            if (!_instanceArray){
                _instanceArray = new Array();
            }
            return _instanceArray;
        }
 
    }
 
}

UPD 2alatar - написал не увидев твоего сообщения..

chabapok 16.10.2010 18:56

люди, какой наблюдатель? Какое регистрить? Все гениальное - просто, а сложное - не нужно.
Код AS3:

for(var i=0; i<numChildren;i++)
if ( !(getChildAt(i) is MyClass) ) continue;
else{обработать getChildAt(i) }

если объекты расположены вложено - можно вызывать такую функцию рекурсивно

TanaTiX 16.10.2010 19:08

ну это во первых только если все экземпляры находятся в одном контейнере
во-вторых, смысл перелопачивать дохерища объектов (а их может быть еще больше:) ), когда можно взять только нужное?
Ну и рекурсия тут явно не оправдана

i.o. 16.10.2010 19:24

Цитата:

во-вторых, смысл перелопачивать дохерища объектов (а их может быть еще больше ), когда можно взять только нужное?
TanaTiX, читаем вопрос внимательно:
Цитата:

Можно ли, каким-то образом, обратиться сразу ко всем экземплярам определенного класса, которые отображены на сцене?
Перелопачивать в любом случае придется - в первом по всем детям на сцене проходить и смотреть их класс. Второй - брать (если реализовать как у Котяры через статик массив) все экземпляры класса и смотреть, являются ли они детьми сцены.
Вывод - первый способ реализуем с меньшим гимором и он не может привести к утечкам памяти, в то время как во втором способе, можно "забыть" удалить экземпляр из статик массива, когда объект станет ненужным.

TanaTiX 16.10.2010 20:30

i.o., зачем перелопачивать ВСЕ, когда можно иметь список нужного? Нет желания использовать статик - юзаем сингл. А если соответствующему классу (экземпляру) при добавлении на сцену прописать автоматическое добавление в массив (напр. метод register), а удалять другим методом (к примеру destroy), удаляя его при этом из соответствующего массива. Думаю что это более привлекательное решение.

gloomyBrain 16.10.2010 21:15

Цитата:

можно "забыть" удалить экземпляр из статик массива, когда объект станет ненужным
Так ведь можно и со сцены забыть его удалить =) Выше предложена реализация (ADDED_TO_STAGE, REMOVED_FROM_STAGE) при которой забыть не получится. В данном случае солидарен со всеми, кто за статичый массив

i.o. 16.10.2010 21:38

Не вижу смысла отягощать дополнительными функциями класс, заморачиваться на слушание событий типа ADDED_TO_STAGE / REMOVED_FROM_STAGE. Хранить это все еще где-то. Когда задача поставлена предельно просто и ясно: перебрать все объекты на сцене определенного класса. Зачем вот надо придумывать лишнее, когда конкретно в данном случае можно обойтись одной-единственной функцией. А для гибкости, можно класс динамически подсовывать:
Код AS3:

function getChildrenOfClass( container:DisplayObjectContainer, classToMatch:Class ):Array
{
        if( !container || !classToMatch )
                return null;
 
        var outInstances:Array = [];
        var d:DisplayObject;
        var i:int = container.numChildren;
        while( i-- )
        {
                d = container.getChildAt( i );
 
                if( d is classToMatch )
                        outInstances.push( d );
        }
 
        return outInstances;
}

Пример юзания:
Код AS3:

var shapes:Array/**Shape*/ = getChildrenOfClass( root as DisplayObjectContainer, Shape );

(Код не компилил, мог пропустить какую-нибудь мелкую ошибку).

Автор не ставил задачу "максимально быстро", где возможно было бы оправдано пихать лишний функционал в кастомные классы.
Приведенный пример максимально гибок / абстрактен и может быть использован независимо от реализации кастомных классов.

mayakwd 16.10.2010 21:40

@i.o.:

а если объекты искомого класса находятся внутри другого объекта находящегося на сцене, предлагаете рекурсивно бегать по всем DisplayObjectContainer'ам?

i.o. 16.10.2010 21:45

mayakwd, а что у вас на сцене тысячи объектов валяются, что это может сказаться на переборе, даже рекурсивном? Если да, то постом выше сказано:
Цитата:

Автор не ставил задачу "максимально быстро", где возможно было бы оправдано пихать лишний функционал в кастомные классы.
В таком варианте - я ничего не имею против, если от этого есть реальная выгода.

mayakwd 16.10.2010 21:58

@i.o.:

я считаю что код должен быть продуктивным, и, что не стоит делать частных решений.

TanaTiX 16.10.2010 21:59

i.o., не было задачи "перебрать все элементы", была задача "выбрать нужные". А ваш вариант хоть и имеет правл на жизнь, но вданном контексте ИМХО менее "ООПшный", мы же не gc пишем.

i.o. 16.10.2010 22:01

Вот статик массив, как раз, есть частное решение. То что я предложил - общее.

TanaTiX
Если вам платят за количествно набранных строк и за "только ООПшный код", а не за здравый взгляд на мир вещей, то я понимаю ваше несогласие.

andrew911 16.10.2010 22:13

Цитата:

Сообщение от mayakwd (Сообщение 943180)
@i.o.:

я считаю что код должен быть продуктивным, и, что не стоит делать частных решений.

ИМХО для продуктвиности как раз и делаются частные решения ;)))
Так как условия и цели в разных случаях могут различаться, не бывает универсального кода.

mayakwd 16.10.2010 22:19

Цитата:

Сообщение от andrew911 (Сообщение 943183)
ИМХО для продуктвиности как раз и делаются частные решения ;)))
Так как условия и цели в разных случаях могут различаться, не бывает универсального кода.

пожалуй я не буду спорить.
вырвать из контекста можно что угодно )

i.o. 16.10.2010 22:27

Цитата:

я считаю что код должен быть продуктивным
Ну вот вы меня прям-таки вынудили сделать тесты для своего непродуктивного кода.. Честно говоря ожидал хуже.
В упрощенном виде тест такой:
Код AS3:

//{ filling
 
var myContainer:Sprite = new Sprite();
 
i = -1;
while( ++i < 100*1000 )
        myContainer.addChild( new Shape() );
 
i = -1;
while( ++i < 100*1000 )
        myContainer.addChild( new Sprite() );
 
//} filling
 
 
var tm01:int = getTimer();
 
result = getChildrenOfClass( myContainer, Shape );
 
tm01 = getTimer() - tm01;
 
// tm01: 35ms

Как мы видим, провал в 35мс появляется только при переборе и проверке 200'000 (двухсот тысяч) детей в контейнере.
Как же непродуктивно!... :p:p

mayakwd 16.10.2010 22:30

подобные тесты не дают никаких реальных данных B-)
тем более глубина вложенности у вас равна единице =)

i.o. 16.10.2010 22:35

вам двести тысяч детей о чем-то говорит? Это сделано с учетом того, что в реальности даже во всем древе сцены столько детей никогда не будет. Но даже при такой тяжести все про все отнимает 35 мс. С рекурсивным проходом в два раза медленнее не станет, поверьте.
Можете стоять на своем, мне до этого дела нет.
Вообще, рекоммендую поинтересоваться у автора - ему это для авариума с рыбкой нужно?

passertm 16.10.2010 23:06

ну кучу хороших вариантов названо.
в зависимости от случая можно и пройтись по всем обьектам(количество их может быть слишком большим) или юзать один из названных патернов(большой минус возможность утечьки памяти ведь при удалении обьекта отовсюду на него еще останется ссылка из храниша. а в большом проекте перекопать все места где удаляются обьекты может быть не так просто).

у меня только один вопрос. почему
Код AS3:

for(var i=0; i<numChildren;i++)
if ( !(getChildAt(i) is MyClass) ) continue;
else{обработать getChildAt(i) }

а не
Код AS3:

for(var i=0; i<numChildren;i++)
if (getChildAt(i) is MyClass ) {
обработать getChildAt(i)
}

))))))

Добавлено через 11 минут
тьфу. я чето только первую страницу прочитал подумал на этом и остановились :))))))
200 тысяч за 35 милли секунд это бычтро. очень даже по моему. не ожидал

Котяра 16.10.2010 23:21

ну вообще я как и tanatix советую помещать объекты в массив при создании, без всяких статиков итп...
типа так:
Код AS3:

var enemy:Enemy = new Enemy();
this.enemyList.push(enemy);

всё. нужны враги - обходим врагов, нужны призы - обходим призы.

f.g.programmer 17.10.2010 00:22

Код AS3:

тьфу. я чето только первую страницу прочитал подумал на этом и остановились

Я тоже :) И мой комментарий оказался очень похож на комментарий gloomyBrain вначале второй страницы.
Это недостаток дизайна. Было бы удобно, если бы под последним комментарием была достаточно заметная кнопка "СЛЕДУЮЩАЯ СТРАНИЦА", если такая есть.

gloomyBrain 17.10.2010 00:54

Задача:
Цитата:

обратиться сразу ко всем экземплярам определенного класса, которые отображены на сцене
Решение i.o.
Цитата:

Пройтись по каждому экземпляру и проверить, является ли он наследником определенного класса, с помощью оператора is
Проверки на соответствие по классу нет в условии задачи и для ее решения проверка так же не требуется. Тем более рекурсивная. Следовательно, это просто лишняя работа.

Добавка от passertm:
Цитата:

большой минус возможность утечьки памяти ведь при удалении обьекта отовсюду на него еще останется ссылка из храниша
Если у объекта есть метод destroy() или у класса есть статический метод removeInstance() (оба метода могут быть private и вызываться по событиям REMOVED_FROM_STAGE), то вопрос снимается автоматически. Говоря про утечки памяти - удаление элемента массива не есть трудоемкая операция, равно как и удаление со сцены. Так что аргумент в расчет не принимается.

Мнение mayakwd:
Цитата:

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

chabapok 17.10.2010 01:17

Вы тут спорите ни о чем. Главное - идея. Идеи подкинули -- дальше пускай топикстартер сам решает что ему нужно.

может ему нужно перебирать эти экземпляры 1 раз при запуске. А может в каждом событии ENTER_FRAME. Требования к оптимизации, естественно разные.

passertm 17.10.2010 10:35

Цитата:

Сообщение от f.g.programmer (Сообщение 943205)
Это недостаток дизайна. Было бы удобно, если бы под последним комментарием была достаточно заметная кнопка "СЛЕДУЮЩАЯ СТРАНИЦА", если такая есть.

да. есть номера страниц. просто они находятся после формы ввода быстрого ответа. вот и получается что сначало отвечаем:)

Добавлено через 25 часов 28 минут
Цитата:

Сообщение от gloomyBrain (Сообщение 943207)
Если у объекта есть метод destroy() или у класса есть статический метод removeInstance() (оба метода могут быть private и вызываться по событиям REMOVED_FROM_STAGE), то вопрос снимается автоматически. Говоря про утечки памяти - удаление элемента массива не есть трудоемкая операция, равно как и удаление со сцены. Так что аргумент в расчет не принимается.

вот в этом и есть беда. в кажужейся простоте реализации. к примеру после такой реализации. обьект может быть добавлен на сцену а потом удален и потом вновь добавлен и вот дела. всеми подобным обьектами на сцене производится действия а с одим нет. убиться можно пока найдешь причину если обьектов больше 1000(т.к. удаление и добавление могло произойти на пол часа до того как что то пойдет не так).

я не пытаюсь показать будто этот метод сложнее чем есть на самом деле. наличие нужных событий очень упрашает дело. но все же есть случаи в которых я бы предпочел делать перебор. ибо игра не стоилобы свечь(реализации этого всего и отладки чтобы убедиться что все идет как надо)

alatar 18.10.2010 13:41

Цитата:

но все же есть случаи в которых я бы предпочел делать перебор.
Перебор будет проще в весьма ограниченном колличестве случаев (когда нужные объекты преобладают над остальными), в остальном такая реализация будет более затратна для ресурсов (представьте, что у вас на сцене есть система чатиц и ваш алгоритм перебора натыкается на нее).
Цитата:

...обьект может быть добавлен на сцену а потом удален и потом вновь добавлен и вот дела...
Это уже будет кривизна конкретной реализации, сам метод (сбор ссылок на экземпляры) предельно прост, накосячить в нем, это надо постараться.

gloomyBrain 18.10.2010 13:43

Цитата:

накосячить в нем, это надо постараться
Вот я тоже так думаю. Там отлаживать-то 3 (ну ладно - 4) строчки кода =)

passertm 18.10.2010 14:21

Цитата:

Сообщение от alatar (Сообщение 943495)
Перебор будет проще в весьма ограниченном колличестве случаев (когда нужные объекты преобладают над остальными), в остальном такая реализация будет более затратна для ресурсов (представьте, что у вас на сцене есть система чатиц и ваш алгоритм перебора натыкается на нее).

почему же. для отладки на пример. если на сцене очень мало обьектов. если действие нужно сделать один раз за время выполнения программы. или просто делать крайне редко.

Цитата:

Сообщение от alatar (Сообщение 943495)
Это уже будет кривизна конкретной реализации,

ну да. но именно этот метод предложил товарисч подумав что этого достаточно. и прочитав я тоже решил было что этого достаточно(до меня поздно доходит:quiet:) и того 2 программиста которые пытаясь реализовать этот "простенкий" код заработали бы себе хорошую головную боль(молчу про автора статьи который получил совет сделать это так). именно поэтому я и сказал что не хочу показать код сложнее чем есть. но всеровно это(т.е. любой код которому нужно бывает работать в течении долгого времени) сложнее чем код который запускается выполняется и заканччивается ибо в случаях проблем такие коды намного проше отладить.

я повторюсь я не говорю что ваш метод плох. и есть много случаях когда я бы использовал и его. просто мое сугубое личное мнение(с языков в которых подобная реализация не так проста) что с подобными кодами лучше быть осторожнее)

i.o. 18.10.2010 16:06

Форум не без людей, которые пишут ООП ради ООП, даже если тем, что они пишут, нужно воспользоваться один раз.

Добавлено через 21 минуту
Да и вообще весь спор глупый. Автор не уточнил ситуацию.
Что из себя представляет сцена?
Добавлена ли она на стейдж?
Как часто он собирается проходить по всем объектам определенного класса?
Что из себя представляет определенный класс? Может это обычные Sprite, Shape, MovieClip и Bitmap. Тогда вы предлагаете контейнеру-сцене подписываться на фазу захвата для событий ADDED / REMOVED, чтобы добавить / удалить объект из списка?
Если определенных классов используется несколько, то на каждый вести список?
Поэтому, прежде чем отстаивать ту или иную точку зрения, нужно вначале выяснить все детали ситуации, а потом уже решать, что оптимальнее всего подходит.

alatar 18.10.2010 16:29

Цитата:

Сообщение от passertm (Сообщение 943511)
...и того 2 программиста которые пытаясь реализовать этот "простенкий" код заработали бы себе хорошую головную боль

Эти же 2 программиста заработают себе головную боль и при рекурсивном переборе объектов.
Цитата:

но всеровно это(т.е. любой код которому нужно бывает работать в течении долгого времени) сложнее чем код который запускается выполняется и заканччивается ибо в случаях проблем такие коды намного проше отладить.
"Это" даже проще в реализации, чем перебор всего и вся. В отладке тоже проще.

i.o. 18.10.2010 16:30

Цитата:

Эти же 2 программиста заработают себе головную боль и при рекурсивном переборе объектов.
Приведите пример этой самой головной боли

alatar 18.10.2010 16:31

i.o., согласен, уже пошла сплошная демагогия :)

i.o. 18.10.2010 16:32

я тоже согласен, но вы меня задели за живое - приведите пример головной боли))

passertm 18.10.2010 16:34

Цитата:

Сообщение от i.o. (Сообщение 943531)
нужно вначале выяснить все детали ситуации, а потом уже решать, что оптимальнее всего подходит.

+1


любопытно. для обьектов которые были добавлены в гуях влеша а не программным путем вызываются событий ADDED

Котяра 18.10.2010 16:52

Топикстартер сделал вброс и пропал)
Давайте может закругляться? По вопросу более-менее ответили..

alatar 18.10.2010 16:52

Цитата:

Приведите пример этой самой головной боли
Объекты есть, они лежат в контейнере, но контейнер не добавлен в список отображения. Итого, они не обработаны.
Встречный вопрос, какова головная боль при добавлении / удалении объектов в статический список, с последующей обработкой или обработкой в процессе добавления / удаления?

i.o. 18.10.2010 16:55

Цитата:

Объекты есть, они лежат в контейнере, но контейнер не добавлен в список отображения. Итого, они не обработаны.
И как это может отразиться на ф-ции перебора?? Она все равно пройдется по всем детям и детям детей (если модифицировать в рекурсивную).
Зато в конкурирующем примере, где слушается ADDED_TO_STAGE / REMOVED_FROM_STAGE, получится:
Цитата:

Итого, они не обработаны
Цитата:

Встречный вопрос, какова головная боль при добавлении / удалении объектов в статический список, с последующей обработкой или обработкой в процессе добавления / удаления?
Усложнение разработки / кода. В то время как я предлагаю одну единственную функцию, не зависящую от проекта вообще.

В общем спорить бесполезно о том какая реализация лучше - читай выше.


Часовой пояс GMT +4, время: 14:14.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.