2008-11-15 80 views
1

這段代碼是blunderous的,因爲它向一個數組中添加了一個類,然後試圖將它拉出來並操作它,就好像它是一個對象一樣。爲什麼Flex讓我把一個類當作一個對象

private function fail(event:Event):void 
{ 
    var myObj:MyClass; 
    var a:ArrayCollection = new ArrayCollection(); 
    var x:MyClass; 
    var y:MyClass; 

    myObj = new MyClass; 
    a.addItem(myObj); 
    a.addItem(MyClass); // !!BAD!! 

    x = a[0]; 
    y = a[1]; 
} 

當我意外地做了這件事,我花了我一輩子纔看到我做錯了什麼。部分原因是錯誤信息沒有告訴我任何我能理解的東西:

TypeError: Error #1034: Type Coercion failed: cannot convert com.ibm.ITest::MyClass$ to com.ibm.ITest.MyClass. 
    at ITest/fail()[C:\work_simple01\ITest\src\ITest.mxml:51] 
    at ITest/___ITest_Button5_click()[C:\work_simple01\ITest\src\ITest.mxml:61] 

所以我的問題是,爲什麼這行標記!!壞!以上甚至允許?我期望在這裏編譯時錯誤。自編譯以來,我一定不知道這個用法。它是什麼?

回答

8

這個問題在我看來相當於「爲什麼我可以使用一個類作爲一個值?」這是一個很好的問題。

在ActionScript中,您可以使用類來做兩件大事:你可以實例化它它,你可以訪問它的靜態合作伙伴。 (好吧,還有其他的東西,但這些是明顯的。)實例化一個類可能是一個類最相關的用法,該類是它自己的factory,就像你要用C++或Java明確指出的那樣。

下面是一個我寫作練習的小俄羅斯方塊遊戲的例子。我有兩個類,Brick和SceneBrick。一塊磚塊是一塊遊戲中的磚塊,那些堆積起來的磚塊。一個SceneBrick是一塊剛剛插入的作爲遊戲區框架的磚塊。

但是,我用一個函數來繪製他們兩個,沒有提及任何類型的函數中:

function drawBricks(xs:Array, ys:Array, brickType:Class){ 
xs.map(function(o,i,a){ 
    var brick = new brickType(); 
    // etc. 
});  
} 

而且我可以使用這樣的:

drawBricks([0,1,2,3], [4,4,4,4], Brick); // draw a long piece 
drawBricks(times(0, 21), countFrom(0, 21), SceneBrick); // draw a big vertical "wall" 

在ActionScript中,你可以傳遞一個類作爲一個值並用它來實例化這個類。在像Java或C++這樣的語言中,您必須將其用作泛型類的參數,或者使用一些常見的超類型定義工廠類來完成此操作。

7

我假設你的示例的最後一行出現異常,而不是你標記爲'壞'的錯誤。

添加到數組中的對象表示類MyClass而不是MyClass的實例。

能夠在運行時檢查類是一個強大的功能,是.NET和Java中反射功能的基礎。這些功能通常用於支持可擴展性模式或實現序列化框架。

因此,操縱這些對象之一是一件有效的事情......因爲它不是MyClass的實例,因此您不能將它分配給您的y變量。

0

關於後期綁定(和動態語言)的好處是,它允許您在實現中有更多的靈活性。缺點是這種語言並不能保護你免於犯一些簡單的錯誤,即早期的綁定和強大的輸入阻止。就我個人而言,我會考慮使用TDD(測試驅動開發)作爲一種輔助,以防止這些類型的錯誤蔓延到您的代碼中。

1

看起來像在Flex中,集合沒有指定它們應該包含的值的類型。

var a:ArrayCollection = new ArrayCollection(); 

所以我覺得編譯器不檢查你添加到它的值的類型是合乎邏輯的。然後,只能在運行時檢查收集元素中的變量,因爲編譯器沒有這些信息。對於作爲對象的類(以及對消息的響應),構建各種調試/檢查/反射工具是非常方便的。

相關問題