2008-11-15 62 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(); 

所以我觉得编译器不检查你添加到它的值的类型是合乎逻辑的。然后,只能在运行时检查收集元素中的变量,因为编译器没有这些信息。对于作为对象的类(以及对消息的响应),构建各种调试/检查/反射工具是非常方便的。

相关问题