我试图创建一个适用于Flash中任何类似数组的对象的函数,但我真的很难找到让编译器知道我在做什么的方法。我需要在参数上使用indexOf之类的函数,但除非将其强制转换为正确的数据类型,否则编译器不知道该方法是否可用。令人沮丧的是因为Vector和Array共享几乎相同的界面,但没有一个界面可以反映出来!
目前我已经得到了这个:
private function deleteFirst(tV:* , tVal:*):void {
trace(tV)
var tIndex:int
if (tV is Array) {
var tArray:Array = tV as Array
tIndex = tArray.indexOf(tVal)
if (tIndex >= 0) tArray.splice(tIndex, 1)
} else if (tV is Vector.<*>) {
var tVObj:Vector.<*> = tV as Vector.<*>
tIndex = tVObj.indexOf(tVal)
if (tIndex >= 0) tVObj.splice(tIndex, 1)
} else if (tV is Vector.<Number>) {
var tVNum:Vector.<Number> = tV as Vector.<Number>
tIndex = tVNum.indexOf(tVal)
if (tIndex >= 0) tVNum.splice(tIndex, 1)
} else if (tV is Vector.<int>) {
var tVInt:Vector.<int> = tV as Vector.<int>
tIndex = tVInt.indexOf(tVal)
if (tIndex >= 0) tVInt.splice(tIndex, 1)
} else if (tV is Vector.<uint>) {
var tVUInt:Vector.<uint> = tV as Vector.<uint>
tIndex = tVUInt.indexOf(tVal)
if (tIndex >= 0) tVUInt.splice(tIndex, 1)
}
trace(tV)
}
它有点有效,但它并不完全优雅!我想知道是否有一个我不知道的伎俩。理想情况下,我通过扩展基类来做到这一点,但我不认为可以使用Vector。
由于
答案 0 :(得分:0)
这绝对是AS3的昙花一现,我认为没有任何优雅的解决方案。
但是,您可以进行一次代码简化:
由于indexOf()
和splice()
的语法对于数组和向量都是相同的,因此您不需要使用大的if / else梯形图来转换每个类型。您只需在对象上调用indexOf()
和splice()
,无需任何转换。当然,您在IDE中没有获得任何代码提示,但它的工作方式与您目前的相同。例如:
function deleteFirst(arrayOrVector:* , searchValue:*):* {
if (arrayOrVector is Array || arrayOrVector is Vector.<*> || arrayOrVector is Vector.<Number> || arrayOrVector is Vector.<int> || arrayOrVector is Vector.<uint>) {
var index:int = arrayOrVector.indexOf(searchValue)
if (index >= 0)
arrayOrVector.splice(index, 1)
}else
throw new ArgumentError("Argument 'arrayOrVector' must be an array or a vector, but was type " + getQualifiedClassName(arrayOrVector));
return arrayOrVector;
}
你甚至可以跳过整个if / else类型检查它仍然可以工作,它只会让代码更加混乱,如果用一个参数而不是数组调用函数,你会得到一个稍微混乱的错误vector(如果偶然传递了一个sprite对象,就像“在Sprite类型中找不到indexOf那样”。)
另外值得一提的是,虽然这对数字基类型向量没有帮助,但对于其他向量,您可以排序使用Vector.<*>
作为通用向量引用。您可以使用带有通配符Vector.<*>(myVector)
的{{3}}来分配引用,它将返回对原始向量的引用,而不是通常的新副本。如果您不介意返回基于数字的类型向量的副本而不是始终修改原始向量,您仍然可以利用它来简化代码:
function deleteFirst(arrayOrVector:* , searchValue:*):* {
if (arrayOrVector is Array) {
var array:Array = arrayOrVector;
var index:int = array.indexOf(searchValue)
if (index >= 0)
array.splice(index, 1)
return array;
}else if(arrayOrVector is Vector.<*> || arrayOrVector is Vector.<Number> || arrayOrVector is Vector.<int> || arrayOrVector is Vector.<uint>) {
var vector:Vector.<*> = Vector.<*>(arrayOrVector);
index = vector.indexOf(searchValue);
if (index >= 0)
vector.splice(index, 1);
return vector;
}
throw new ArgumentError("Argument 'arrayOrVector' must be an array or a vector, but was type " + getQualifiedClassName(arrayOrVector));
}
答案 1 :(得分:0)
我会非常小心混合和匹配矢量和数组。它们之间最大的区别是数组是稀疏的,而矢量是密集的。
那就是说,这是你非常紧凑的通用删除功能,可以在任何&#34;设置&#34;具有indexOf和splice ...的类
WebGL
您可以使用此代码
测试代码function deleteFirst( set:Object, elem:Object ) : Boolean
{
if ( ("indexOf" in set) && ("splice" in set) )
{
var idx:int = set.indexOf( elem );
if ( idx >= 0 )
{
set.splice( idx, 1 );
return true;
}
}
return false;
}
更新 - 仅限@Arron,我做了以下更改。请注意,获得异常是好的。它们提供了丰富的信息,有助于揭示代码路径的问题。
var arr:Array = [ 1, 2, 3, 4, 5 ];
var vec:Vector.<int> = new Vector.<int>();
vec.push( 1, 2, 3, 4, 5 );
deleteFirst( arr, 2 ); // will remove 2
deleteFirst( vec, 3 ); // will remove 3
deleteFirst( "aaa4", "4" ); // nothing, cuz String doesn't have splice
trace( arr );
trace( vec );
有!现在它更简单了。你会得到一个例外情况,告诉你错误!