Предоставляет ли AS3 какой-либо способ остановить изменение возвращаемого объекта? - PullRequest
0 голосов
/ 29 октября 2010

Если метод AS3 возвращает ссылку на сложный тип, есть ли способ сделать это «только для чтения», например, как вы можете иметь функции-члены const в C ++?Архитектура, которую я хочу использовать, вызывает сам процесс создания класса из переданного объекта шаблона ... и действительно, объект шаблона не должен быть изменяемым.В настоящее время я вынужден добавить перечислители с обратным вызовом и / или множество дополнительных методов доступа.

Ответы [ 4 ]

2 голосов
/ 29 октября 2010

Flex имеет метод ObjectUtil.clone(), который делает глубокую копию.Копия все равно будет изменяемой, но, поскольку она является копией, изменения не будут распространяться обратно на оригинал.

Метод не сложен, поэтому, если вы не используете Flex, просто добавьте его в утилитукласс:

public static function copy(value:Object):Object
{
    var buffer:ByteArray = new ByteArray();
    buffer.writeObject(value);
    buffer.position = 0;
    var result:Object = buffer.readObject();
    return result;
}
1 голос
/ 30 октября 2010

Неизменяемые интерфейсы почти эквивалентны константности.Вот пример:

interface CPoint {
    function get x():Number;
    function get y():Number;
}

class Point implements CPoint {
    private var _x:Number;
    private var _y:Number;

    public function get x():Number { return _x; }
    public function get y():Number { return _y; }

    public function set x(val:Number) { _x = val; }
    public function set y(val:Number) { _y = val; }

    public function normalize():void {
        var length:Number = Math.sqrt(_x*_x + _y*_y);
        _x /= length;
        _y /= length;
    }

    public function Point(x:Number, y:Number) {
        _x = x; _y = y;
    }
}

Если вы возвращаете Point в качестве ссылки CPoint, то ее поля не могут быть изменены.Вы можете сделать явное приведение к точке из CPoint для принудительного доступа, но вы можете сделать то же самое с константным приведением в C ++.

К сожалению, AS3 не поддерживает ковариацию, как должно, поэтомуизлишне сложно для const подобъектов.Например, если у вас был класс Line, состоящий из двух точек, вы можете сказать line.start.x = 47;, если у вас есть полный доступ к линии, но разрешить чтение line.start.x через неизменный интерфейс.Вы могли бы сделать это, если бы была ковариация, но вместо этого вам нужно будет добавить отдельные свойства get для изменяемых и неизменяемых свойств.Таким образом, вместо этого вы получите line.cstart.x для чтения из CLine.Примерно так:

interface CLine {
    function get cstart():CPoint;
    function get cend():CPoint;
}

class Line implements CLine {
    private var _end:Point;
    private var _start:Point;

    public function get cend():CPoint { return _end; }
    public function get cstart():CPoint { return _start; }
    public function get end():Point { return _end; }
    public function get start():Point { return _start; }

    public function Line(x1:Number, y1:Number, x2:Number, y2:Number) {
        _start = new Point(x1, y1);
        _end = new Point(x2, y2);
    }
}
1 голос
/ 29 октября 2010

Нет способа сделать это в AS3, есть способ Сэма, но он все равно требует копирования этого объекта, прежде чем вы его вернете, в зависимости от сложности этого объекта, это может повлиять на производительность.

0 голосов
/ 30 октября 2010

Я бы создал объект flash.utils.proxy.Вы можете создать прокси-объект, который имеет реализацию только для чтения дочернего объекта, который передается внутрь.

Вот документация для создания прокси-объекта.http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/utils/Proxy.html

Примечание. Прокси работает довольно медленно, так как вы будете обходить проверку нативных объектов и заменять ее вызовом функции, что при использовании большого количества будет медленным.Сначала я бы сделал несколько простых тестов производительности.

Примечание: это псевдокод.

use namespace flash_proxy;

dynamic class ReadOnly extends flash.utils.Proxy {

    private var target:Object;

    public function ReadOnly(target:Object) {
        this.target = target;
    }

    flash_proxy function getProperty(name:*):*
        return target[name];
    }

    flash_proxy function setProperty(name:*, value:*):void
        // throw an error or do nothing
    }

}

Затем вы можете сделать:

var readOnly:ReadOnly = new ReadOnly(stage.loaderInfo.parameters);
readOnly.someparameter = 'newvalue';
trace(readOnly.someparameter); // should be old value
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...