AS3:创建一个接受 Array 和 Vector 作为参数的函数

AS3: Create a function that accepts both Array and Vector as an argument

我正在尝试创建一个适用于 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)
}

有点效果,但不够优雅!我想知道我是否缺少一个技巧。理想情况下,我会通过扩展基础 class 来做到这一点,但我认为 Vector 不可能做到这一点。

谢谢

这绝对是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 类型检查,它仍然可以工作,它只会让代码更混乱,如果你用参数调用函数,你会得到一个稍微更混乱的错误除了数组或向量(如 "indexOf not found on type Sprite" 如果你不小心传递了一个 sprite 对象)。

另外值得一提的是,虽然这对数字基类型向量没有帮助,但对于其他向量,您可以某种使用Vector.<*>作为通用矢量参考。您可以使用带通配符 (Vector.<*>(myVector)) 的 Vector global function 分配引用,它将 return 引用原始向量而不是像通常那样创建新副本。如果您不介意 return 复制基于数字的类型向量而不是总是修改原始向量,您仍然可以利用它来简化代码:

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));
}

我会非常小心地混合和匹配向量和数组。它们最大的区别就是Arrays是稀疏的,而Vector是稠密的。

就是说,这是您非常紧凑的通用删除函数,可用于任何具有 indexOf 和拼接的 "set" class...

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;
}

您可以使用此代码测试代码

        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 );

更新 - 仅针对@Arron,我进行了以下更改。请注意,获得异常是好的。它们内容丰富,有助于揭示代码路径的问题。

function deleteFirst( set:Object, elem:Object ) : Boolean
{
    var idx:int = set.indexOf( elem );
    if ( idx >= 0 )
    {
        set.splice( idx, 1 );
        return true;
    }
    return false;
}

到了!现在更简单了。你得到一个异常,告诉你哪里出了问题!