2010-10-29 73 views
0

如果一个AS3方法返回一个复杂类型的引用,有没有什么办法可以做到“只读”,就像你如何在C++中使用const成员函数一样?我想要使​​用的体系结构要求通过传递的模板对象构建自己的类...并且实际上模板对象不应该是可修改的。我目前被迫添加回调枚举器和/或许多额外的存取器方法。AS3是否提供了阻止正在修改的返回对象的方法?

+0

是你能找到这个问题的答案? – Gunslinger47 2010-11-03 09:08:32

回答

2

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

即使这工作正常,你仍然增加了复制对象的成本。 – dotminic 2010-10-29 19:44:25

+0

@__dominic,是的,还有额外的记忆。它虽然达到了目标。另一种方法是用'ReadOnly'标志创建所有的类,一旦设置就会让所有的设置者抛出一个错误,但这将是很多工作。 – 2010-10-29 20:01:55

+0

由于AS3不提供实现const成员函数的方法,因此您的实现很好。在const成员方法中抛出错误并不是一个坏主意,但它会像你说的那样添加大量的样板代码。 – dotminic 2010-10-29 20:08:21

1

有没有办法做到这一点在AS3中,有这样做的Sam的方式,但它仍然需要在返回它之前复制该对象,具体取决于该对象的复杂程度,它可能会影响性能。

1

不可变接口对于const正确性是近似等价的。这里有一个例子:

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对一个Point进行显式强制转换来强制访问,但是你可以用C++中的const强制转换做同样的事情。

不幸的是,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); 
    } 
} 
0

我会创建一个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 
相关问题