2010-10-29 68 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 
相關問題