Форум 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=159403)

FinalBoss 30.06.2011 16:54

Типизированный массив, расширяющийся при необходимости
 
Всем привет.

У меня есть массив одинаковых объектов, к примеру 10 мувиклипов, а мне нужно разместить на экране 15 таких мувиков из этого массива. Для этого нужно заполнить этот массив ещё 5 объектами этого же типа.
Т.е нужно создать такую функцию, которая расширяла бы указанный массив, нужным типом данных ... понятно что можно внутри такой функции реализовать switch в котором будут указаны все типы, но может есть способ поэлегантнее? чтобы при появлении нового класса не надо было добавлять соответсвующий case ? Либо может как-то расширить класс Array или Vector так чтобы его можно было влюбой момент дополнить?

Спасибо!

bav 30.06.2011 16:57

По-моему в Array и так можно когда и куда угодно добавлять что угодно.

kackbip 30.06.2011 16:58

вроде есть метод один... getQualifiedClassName... вроде называется.
В параметры принимает объект.
Получаете имя класса, потом получаете сам класс: getDefinitionByName
Потом создаете экземпляры
---
если я правильно понял, что нужно автору

FinalBoss 30.06.2011 17:10

Цитата:

Сообщение от bav (Сообщение 1007725)
По-моему в Array и так можно когда и куда угодно добавлять что угодно.

Скажу иначе, у меня есть 2 типизированых массива

Код AS1/AS2:

var A:Vector.<Sprite> = new Vector.<Sprite>();
var B:Vector.<Object> = new Vector.<Object>();

мне нужно дополнить ещё тремя и пятью элементами оба массива, для этого я хочу использовать функцию вроде этой:

Код AS1/AS2:

A.add(3);
B.add(5);

Т.е функция add возьмет на себя работу определения нужного типа элементов и добавит нужное их число в массив.
Ну или в более простом виде реализовать, типа как-нить так:

Код AS1/AS2:

AddElementsTo(A, 3, Sprite);
AddElementsTo(B, 5, Object);


kackbip 30.06.2011 17:13

Да, вы можете это реализовать с помощью того, что я описал выше.

FinalBoss 30.06.2011 17:51

Цитата:

Сообщение от kackbip (Сообщение 1007730)
Да, вы можете это реализовать с помощью того, что я описал выше.

Да, все получилось, спасибо!
Состряпал тут для наглядности, может ещё кому пригодится:

Код AS1/AS2:

import flash.utils.getDefinitionByName;
import flash.utils.getQualifiedClassName;
import flash.display.MovieClip;
 
var AArray:Array = new Array();
var BArray:Array = new Array();
 
function AddElementsTo(A:Array, num:int, NeedClass:String):void {
        for (var i:int = 0; i < num; i++) {
                var someClass:Class = getDefinitionByName(NeedClass) as Class;
                A.push(new someClass());       
        }
}
 
function AddElementsTo2(A:Array, num:int, NeedClass:*):void {
        var nameClass:String = getQualifiedClassName(NeedClass) as String;
        trace(nameClass);
        for (var i:int = 0; i < num; i++) {
                var someClass:Class = getDefinitionByName(nameClass.toString()) as Class;
                A.push(new someClass());       
        }
}
 
AddElementsTo(AArray, 3, "flash.display.Sprite"); // указываем нужный класс
AddElementsTo2(BArray, 5, AArray[1]); // реализация, где просто даем ссылку на экземпляр нужного класса
 
trace(AArray + "\n" + BArray);
 
//результат
[object Sprite],[object Sprite],[object Sprite]
[object Sprite],[object Sprite],[object Sprite],[object Sprite],[object Sprite]

Ну похоже тема закрыта

alatar 30.06.2011 18:17

Если вам, на этапе компиляции, известен класс который необходимо создать, то все эти танцы с бубном getQualifiedClassName не нужны. Передавайте в функцию сразу необходимый класс.
Код AS3:

function AddElementsTo2(A:Array, num:int, NeedClass:Class):void {
        for (var i:int = 0; i < num; i++) {
                A.push(new NeedClass());       
        }
}
...
AddElementsTo(AArray, 3, Sprite);


-De- 30.06.2011 18:21

А вам есть разница, писать
Код AS3:

AddElementsTo(AArray, 3, Sprite);

или
Код AS3:

AddElementsTo(AArray, 3, "flash.display.Sprite");

?
в первом случае всё намного легче и быстрее, new NeedClass и всё). Для второго советую вместо
Код AS3:

getDefinitionByName(getQualifiedClassName(NeedClass))

(зачем, кстати, строку эту тягать весь цикл и кучу раз getDefinitionByName дёргать?)
Код AS3:

(NeedClass as Object).constructor

- нет мороки со строками, строки это не особо быстро всегда. Ну и вообще информацию о типах использовать не рекомендуют.

goodguy 30.06.2011 20:15

Может я что-то не понял, но не лучше ли в таком случае использовать Array?
Зачем тут Vector вообще?
По-моему, все преимущества в скорости будут сведены на нет подобной хренью getDefinitionByName(getQualifiedClassName(NeedClass))

Crazy 30.06.2011 20:27

...тем более, что штатно это делается передачей параметром не имени класса или самого класса, а объекта-фабрики. Что и быстрее и гибче.

Изучаем паттерн Abstract Factory и будет счастье.

kackbip 01.07.2011 06:29

Ну у фабрики собственно те же проблемы с добавлением нового типа объектов.

Crazy 01.07.2011 08:57

Цитата:

Сообщение от kackbip (Сообщение 1007910)
Ну у фабрики собственно те же проблемы с добавлением нового типа объектов.

Не могли бы Вы проиллюстрировать свою мысль?

kackbip 01.07.2011 11:19

Я о том, что для каждого типа создаваемых объектов нужна своя конкретная фабрика.

Crazy 01.07.2011 11:28

Цитата:

Сообщение от kackbip (Сообщение 1007940)
Я о том, что для каждого типа создаваемых объектов нужна своя конкретная фабрика.

Это не баг. Это фича.

kackbip 01.07.2011 11:45

Это создание нескольких классов вместо одной строчки.

Crazy 01.07.2011 11:48

Это создание нескольких правильных классов вместо одной кривой строчки.

И давайте, кстати, посмотрим, как выглядит Ваша "одна строчка" не в искусственных тепличных условиях, а в реальной жизни. Для вот такого класса, к примеру:

Код AS3:

public class Foo
{
  private var bar:String;
  public function Foo (var bar:String):void
  {
    this.bar = bar;
  }
}


kackbip 01.07.2011 12:01

А как вы решите с помощью абстрактной фабрики задачу автоматического создания объекта при том, что класс создаваемого объекта на момент создания абстрактной фабрики еще не известен?

Я тоже могу сделать предположения которые выходят за рамки изначальной задачи.
Как говорится делать надо не так как правильно :) А точнее правильно это не то, что соответствует каким-то стандартам и шаблонам. Правильно значит быстро и качественно с учетом поставленной задачи.

Crazy 01.07.2011 12:11

Цитата:

Сообщение от kackbip (Сообщение 1007971)
А как вы решите с помощью абстрактной фабрики задачу автоматического создания объекта при том, что класс создаваемого объекта на момент создания абстрактной фабрики еще не известен?

Коллега, я не очень понял Ваших абстрактных построений. Вы не могли бы их кодом проиллюстрировать? Типа "вот волшебная строчка и так через фабрику сделать не получится"? Тогда у нас будем о чем подискутировать.

Цитата:

Я тоже могу сделать предположения которые выходят за рамки изначальной задачи.
Я это понял как "моя волшебная строчка для класса Foo работать не будет". Ok. Только не очень понятно, почему Вы считаете, что это за рамками изначальной задачи. Там где-то сказано, что классы гарантированно не будут иметь конструкторов с параметрами?

Я Вам помогу, вот текст:


Цитата:

У меня есть массив одинаковых объектов, к примеру 10 мувиклипов, а мне нужно разместить на экране 15 таких мувиков из этого массива. Для этого нужно заполнить этот массив ещё 5 объектами этого же типа.
Т.е нужно создать такую функцию, которая расширяла бы указанный массив, нужным типом данных ... понятно что можно внутри такой функции реализовать switch в котором будут указаны все типы, но может есть способ поэлегантнее? чтобы при появлении нового класса не надо было добавлять соответсвующий case ? Либо может как-то расширить класс Array или Vector так чтобы его можно было влюбой момент дополнить?
Очевидный правильный ответ -- даем на вход реестр фабрик. И получаем решение, которое не протухает при необходимости добавить новый класс -- достаточно будет просто зарегистрировать еще одну фабрику не переделывая ни строчки из уже написанного кода.

Crazy 01.07.2011 12:16

Какая конкретно сигнатура будет у метода добавления?

kackbip 01.07.2011 12:22

Да, Сrazy, вы хороший вариант предложили.
Но в случае, если заранее известно, что конструкторы все таки не будут иметь параметров - проще написать одну корявую строчку:
Код AS3:

new getDefinitionByName(getQualifiedClassName(obj))

или через Object#constructor

Кстати, спасибо. До этого дня я не знал об абстрактной фабрике. Сейчас же нахожу ее крайне полезной.

Crazy 01.07.2011 12:24

Цитата:

Сообщение от kackbip (Сообщение 1007981)
если заранее известно, что конструкторы все таки не будут иметь параметров

...и не потребуется никакая другая инициализация после отработки конструктора -- то да, можно и без фабрики.

FinalBoss 01.07.2011 12:29

Всем спасибо за помощь!

Мне нужно чтобы массив заполнялся элементами указанного мной типа, мувиклипами, спрайтами и т.п. Тип задается через параметр. Я хочу сделать это через класс, расширить класс Array добавив в него функцию add(className:Class, num:int), чтобы он мог дополнять себя объектами className в количестве num объектов.

- конструкотры не будут иметь параметров
- на этапе компиляции класс известен

Попытался составить свой класс, но не знаю как сделать чтобы он вел себя как обычный Array. Мне нужен обычный Array с функцией add, подскажите как должно выглядеть? Спасибо!

Код AS3:

package {
        public class GArray extends Array {
 
                public function GArray():void {
                }
 
                public function add(className:Class, num:int):void {
                        for (var i:int = 0; i < num; i++) {
                                this.push(new className());
                        }
                }               
        }
}


kackbip 01.07.2011 12:45

Crazy, спасибо за урок.(серьезно)

FinalBoss, ваш пример должен быть рабочим.

FinalBoss 01.07.2011 13:11

Цитата:

Сообщение от kackbip (Сообщение 1007992)
FinalBoss, ваш пример должен быть рабочим.

Но он не рабочий, вот что выдает:

ReferenceError: Error #1069: Не удалось найти свойство 0 в GArray; отсутствует значение по умолчанию.
at Array$/_join()
at Function/<anonymous>()
at global/trace()
at Main()

kackbip 01.07.2011 13:16

Я никогда не пробовал расширять массив. :)
Попробуйте добавить модификатор dynamic своему классу.

FinalBoss 01.07.2011 13:20

Цитата:

Сообщение от kackbip (Сообщение 1008022)
Я никогда не пробовал расширять массив. :)
Попробуйте добавить модификатор dynamic своему классу.

Во! Получилось, спасибо за подсказку :)
А так же спасибо всем участникам дискусии!

Psycho Tiger 01.07.2011 21:59

Цитата:

А вам есть разница, писать
Разница есть, если работать с разными аппдоменами.


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

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