我不知道为什么以下代码不起作用。
我只是传递然后将Shape对象作为rest参数进行修复。当对象到达最终函数时,它们跟踪为[对象形状],但是在下一行我收到类型强制失败,说明它无法转换为Shape。
输出:
[object Shape],[object Shape]
TypeError: Error #1034: Type Coercion failed: cannot convert []@27b68921 to flash.display.Shape.
at Test/receiver()
at Test/passer()
at Test()
代码:
package
{
import flash.display.Sprite;
import flash.display.Shape;
public class Test extends Sprite
{
public function Test()
{
//Create Shapes
var myFirstShape:Shape = new Shape();
myFirstShape.graphics.beginFill(0);
myFirstShape.graphics.drawRoundRect(0, 0, 100, 100, 50);
var mySecondShape:Shape = new Shape();
mySecondShape.graphics.beginFill(0);
mySecondShape.graphics.drawRoundRect(0, 0, 100, 100, 50);
//Pass Shapes
passer(myFirstShape, mySecondShape);
}
private function passer(...items):void
{
//Pass Shapes Again
receiver(items);
}
private function receiver(...items):void
{
//Rest Trace As [object Shape], [object Shape]
trace(items);
//Type Coercion Failed ??!!
for each (var element:Shape in items)
{
trace(element);
}
}
}
}
答案 0 :(得分:1)
乍一看这有点反直觉,但它确实有意义......
声明rest参数时,实际传递的参数将在运行时包装在Array中。
这意味着,如果你这样做:
myFunction(1,2,3);
您的函数将收到一个包含3个值的数组。
这正是这里发生的事情:
private function passer(...items):void
{
//Pass Shapes Again
receiver(items);
}
ìtems
本身就是passer
正文中的一个数组。但是当你调用receiver
时,这个包含2个形状的数组被包装在另一个数组中,因为你声明receiver
采用了一个rest参数。
当receiver
中的循环尝试将每个项目转换为形状时,它会失败(因为您无法将Array
转换为Shape
)。
你可以看到这改变了你的代码:
private function receiver(...items):void
{
//Rest Trace As [object Shape], [object Shape]
trace(items);
trace(items.length);// --> traces 1
trace(items[0].length);// --> traces 2; this is the Array you want.
}
因此,根据您真正想要实现的目标,您有几种方法可以解决这个问题。
1)让receiver
“解包”其余参数以获取内部数组。基本上是循环items[0]
而不是items
。
2)将您的功能签名更改为:
private function receiver(items:Array):void
3)更改调用receiver的方式,以便将数组作为参数列表传递:
private function passer(...items):void
{
//Pass Shapes Again
receiver.apply(this,items);
}
这样做的效果相当于:
receiver(items[0],items[1]);
当然,它除了动态处理项目列表外。
如果您确实需要passer
来取休息参数,可以使用选项3)。否则,我会选择选项2)。选项1)是我最不喜欢的,因为它是最脆弱的,但它也是一个有效的选项。