Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Ограничения ByteArray при клонировании (http://www.flasher.ru/forum/showthread.php?t=143737)

XDiaBLo 24.08.2010 18:33

Ограничения ByteArray при клонировании
 
Использую общепринятый метод
Код AS3:

public static function clone(source:Object):* 
                {
                        var copier:ByteArray = new ByteArray();
                        copier.writeObject(source);
                        copier.position = 0;
                        return copier.readObject();
                }

для копирования объекта, и получаю
Цитата:

TypeError: Error #1034: Ошибка типа Coercion: невозможно преобразовать Object@2db3b999 в MemberType.
at Main()
вот вызов
Код AS3:

        var mt:MemberType = new MemberType(maxLength);
        var copy:MemberType = Utils.clone(mt) as MemberType

И на всякий случай весь класс MemberType, хотя я думаю что данных было бы достаточно
Код AS3:

package  
{
        /**
        * ...
        * @author XDiaBLo
        */

        public class MemberType
        {
                public var maxLength:int;
                public var solutionType:Vector.<int>;
                public var energy:Number;
                //Инициализация
                public function MemberType(initLength:int)
                {
                        maxLength = initLength;
                        solutionType = new Vector.<int>(maxLength, true);
                        var i:int;
                        for (i = 0; i < maxLength; i++)
                        {
                                solutionType[i] = i;
                        }
                        for (i = 0; i < maxLength; i++)
                        {
                                tweakSolution();
                        }
                }
                //Подстройка
                public function tweakSolution()
                {
                        var x, y, temp:int;
                        do
                        {
                                x = Utils.getRandom(maxLength);
                                y = Utils.getRandom(maxLength);
                        }while (x == y);
                        temp = solutionType[x];
                        solutionType[x] = solutionType[y];
                        solutionType[y] = temp;
                }
                public function hasQueen(i:int, j:int):Boolean
                {
                        return solutionType[i] == j;
                }
                //Вычисление количества конфликтов.
                public function computeEnergy()
                {
                        trace("computeEnergy()");
                        var i, j:int;
                        var board:Vector.<Vector.<Boolean>> = new Vector.<Vector.<Boolean>>(maxLength, true);
                        for (i = 0; i < maxLength; i++)
                        {
                                board[i] = new Vector.<Boolean>(maxLength, true);
                        };
 
                        var dx:Vector.<int> = Vector.<int>([ -1, 1, -1, 1]);
                        var dy:Vector.<int> = Vector.<int>([ -1, 1, 1, -1]);
                        for (i = 0; i < maxLength; i++)
                        {
                                var tempSol:int = solutionType[i];
                                for (j = 0; j < maxLength; j++)
                                {
                                        if (tempSol == j)
                                        {
                                                board[i][j] = true;
                                        }
                                        else
                                        {
                                                board[i][j] = false;
                                        }
                                }
                        }
                        var conflicts:int = 0;
                        var x, y, tempX, tempY:int;
                        for (i = 0; i < maxLength; i++)
                        {
                                x = i; y = solutionType[i];
                                for (j = 0; j < 4; j++)
                                {
                                        tempX = x; tempY = y;
                                        while(1)
                                        {
                                                tempX += dx[j]; tempY += dy[j];
                                                if ((tempX<0) || (tempX >= maxLength) || (tempY < 0) || (tempY >= maxLength)) break;
                                                if (board[tempX][tempY] == true) conflicts++;
                                        }
                                }
                        }
                        energy = conflicts;
                }
                public function getEnergy():Number
                {
                        trace("getEnergy()");
                        computeEnergy();
                        return energy;
                }
        }
}

Алгоритм который я реализовываю, значения не имеет, но если интересует, могу рассказать.

Добавлено через 23 минуты
То есть ошибка происходит когда я делаю var copy:MemberType = Utils.clone(mt);
А когда делаю var copy:MemberType = Utils.clone(mt) as MemberType;
происходит
Цитата:

TypeError: Error #1009: Не удается вызвать свойство или метод со ссылкой на объект "null".
at Main/draw()
at Main()
когда делаю вызов draw(copy, 250, 10); у которого сигнатура
public function draw(memberType:MemberType, xDelta:int, yDelta:int)

XDiaBLo 24.08.2010 18:58

Мне надо копию создать, чтобы её модифицировать независимо.

Добавлено через 3 часа 3 минуты
В общем поскольку описанное повсюду копирование не работает в данной ситуации, а ничего получше мне не подсказали, плюс вдобавок нельзя перегрузить конструктор, а я бы просто сделал копирующий конструктор, то сделал так:
Код AS3:

public function MemberType(initLength:int, clonedObject:MemberType = null) 
                {
                        if (clonedObject == null)
                        {
                                maxLength = initLength;
                                solutionType = new Vector.<int>(maxLength, true);
                                var i:int;
                                for (i = 0; i < maxLength; i++)
                                {
                                        solutionType[i] = i;
                                }
                                for (i = 0; i < maxLength; i++)
                                {
                                        tweakSolution();
                                }
                        }
                        else
                        {
                                this.maxLength = clonedObject.getMaxLength();
                                this.solutionType = clonedObject.getSolutionType();
                        }
 
                }

Это хотя бы позволяет в обычной ситуации, работать как и было задумано, а в случае копирования, указать например var mt2:MemberType = new MemberType(0, mt); Первый параметр значения не имеет в данном случае. Туповато, но чтож сделать, ограничения языка.

dimarik 24.08.2010 22:34

Такое копирование возможно только для DTO/VO объектов, не имеющих в своем составе методов.
Воспользуйтесь GOF-паттерном Prototype.

XDiaBLo 24.08.2010 22:48

Спасибо, я уже сделал всё, но про прототип я всё равно собираюсь почитать, т.к. ещё два часа назад собирался, только вот своя идея в голову пришла, и отложил чтение. У меня GoF есть даже в бумажном виде. Кстати то решение что я выше привёл, чуток криво. Всё же мне понадобилось
this.solutionType = Utils.clone(clonedObject.getSolutionType());
И я из-за этой забывчивости, так и пропарился с отладкой. Ну ладно хоть алгоритм заработал, находит расстановку ферзей, чтобы не били друг друга.

dimarik 24.08.2010 23:00

У нас (AS) поручают копирование объекта самому себе.

Нечто типа
Код AS3:

class MemberType {
 
    public var maxLength:    int;
    public var solutionType:  Vector.<int>;
    public var energy:          Number;
 
    public function clone():MemberType {
        var o:MemberType = new MemderType();
        o.maxLength = this.maxLength;
        o.energy = this.energy;
        // потому как не примитив, а DTO/VO. Тут поможет именно ByteArray
        o.solutionType = ObjectUtils.copy(this.solutionType);
        return o;
    }
}

С оговорками, конечно. solutionType может содержать и не примитивы, тогда придется пройтись по ним и сделать соответствующие копии.

Добавлено через 10 минут
Однако копии визуальных объектов, созданных в authority mode (без копирования текущего состояния объекта. только первоначальный вид ) можно сделать в рантайме совершенно просто.
Достаточно воспользоваться ссылкой на их конструктор.

См. по теме http://www.flasher.ru/forum/showthread.php?p=912025

-De- 25.08.2010 00:01

А таки почему бы не почитать в хелпе про registerClassAlias, там ещё и примерчики есть) Или название так не понравилось?
С методами обьекты вполне так копируются. Другое дело, что не все, но вот этот MemberType - да.

XDiaBLo 25.08.2010 23:18

Глубокоуважаемый -Де-, ваше сообщение просто исчезло до того, как у меня появилось время всё проверить. Я собирался глянуть про этот метод, но утерял его название, с исчезновением вашего сообщения.

Димарик, ваши идеи конечно интересны, но всё же мне не слишком близка идея забить на инкапсуляцию. Впрочем завтра ещё раз гляну на ваши предложения, так как сегодня уже время позднее. Но надеюсь таки вы поняли, почему я сделал
this.solutionType = Utils.clone(clonedObject.getSolutionType());
а не просто this.solutionType = Utils.clone(this.solutionType);
Опять же думаю переделать свою программу, с использованием SpringActionScript. Нужна практика использования этого замечательного инструмента. А там кругом геттеры и сеттеры и всякие там инъекции, так что возможно придётся обдумать насчёт перенесения многого из конструкторов в сеттеры, хотя я в ЭкшнСкрипте пока в Спринг сильно не погружался, я разделяю работу и домашнее программирование. На работе Джава, дома ЭкшнСкрипт.

Psycho Tiger 26.08.2010 11:58

dimarik, а почему сделать полную копию DO сложно?
Насколько я помню единственная проблема была в graphics - но в 10-ке появился метод copyFrom. Ну и в addChild сделанное вне конструктора, но эта проблема тоже решаема.

dimarik 30.08.2010 23:09

Тигра, сделать копию любого объекта во флеше тяжело.


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

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