开发者

How to test if an object is a vector?

开发者 https://www.devze.com 2023-02-12 17:01 出处:网络
I want to test if an object is a vector, any vector, not only a vector of a single type. I ran a test:

I want to test if an object is a vector, any vector, not only a vector of a single type.

I ran a test:

var v:Vector.<int> = new Vector.<int>();
v.push(3);
v.push(1);
v.push(2);
trace(v is Array); // false
trace(v is Vector); // false
trace(v is Vector.<int>); // true
trace(v is Vector.<*>); // false

It seems that the only thing that returns true is the one which specifies the vector type, but I want to test it for ANY type.

I will need a very efficient method to compare, because getQualifiedClassName is too slow.

My current approach is:

private static func开发者_开发知识库tion isVector(obj:Object):Boolean {
    return (getQualifiedClassName(obj).indexOf('__AS3__.vec::Vector') == 0);
}

But it is 2x slower than the is operator.

I need speed because it's for a object serialization class, and it needs to be very fast.


The problem is that Vector.<*> is a different class than that used for <Number>, <int>, or <uint>. The numeric primitives have special classes for better efficiency. String and Boolean are also primitives, but unlike the numeric primitives they are detected by <*>. As a result, you need only test for the generic Vector and the 3 numeric types.

This solution is over 2 times as fast as getQualifiedClassName in the worst case where the object is either not a Vector, or is a Vector.<uint>, and 5 times faster if the object is a non-primitive base type Vector, like Vector.<Object>:

return (obj is Vector.<*> 
     || obj is Vector.<Number>
     || obj is Vector.<int>
     || obj is Vector.<uint>);

Here's a simplistic test:

var moo:Vector.<uint> = new Vector.<uint>();
var timer:Timer = new Timer();
var b:Boolean;
timer.startTimer();
for (var i:int = 0; i < 1000000; i++)
{
    b = (moo is Vector.<*> 
      || moo is Vector.<Number> 
      || moo is Vector.<int>
      || moo is Vector.<uint>);
}
logger.info("  is timer: " + timer.endTimer());

timer.startTimer();
for (i = 0; i < 1000000; i++)
{
    b = (flash.utils.getQualifiedClassName(moo).indexOf('__AS3__.vec::Vector') == 0);
}
logger.info("gqcn timer: " + timer.endTimer());


[LOG] com.tcg.test:   is timer: 320
[LOG] com.tcg.test: gqcn timer: 756

Change moo to Vector.<Object>:

[LOG] com.tcg.test:   is timer: 158
[LOG] com.tcg.test: gqcn timer: 743


Other methods are way too inefficient, so I'm still using my approach:

private static function isVector(obj:Object):Boolean {
    return (getQualifiedClassName(obj).indexOf('__AS3__.vec::Vector') == 0);
}


trace(new Array().fixed);//undefined
trace(new Object().fixed);//undefined
trace(new Vector.<Sprite>().fixed);//false
trace(new Vector.<*>().fixed);// false


If you need serialization for any kind of object, you have to iterate over all possible types anyway, so you could use a sequential approach to find your vector type:

  1. v is ... (simple data types)
  2. v is ... (object types that are not collections)
  3. v is Array
  4. v is XMLList
  5. v is ... (all other collection types you can think of)
  6. if none of the above is true, it must be a vector
  7. serialize objects in the vector. If you have more than one type, it's Vector.<*>, otherwise set the vector type according to the object type of the content items.


Use

(obj as Vector.<*>) is Vector.<*>


    /// Return Class of any Target
    static public function getClass( Target:* ):Class
    {
        return getDefinitionByName ( getQualifiedClassName( Target ) ) as Class ;
    }

    /// Check if object is type of Vector.< * >
    static public function isVector( any:* ):Boolean 
    {
        return String( getClass( any ) ).indexOf( "[class Vector.<" ) > -1;
    }

    /// Get Vector < Class >
    static public function getVectorType( vector:* ):Class
    {
        var c:String = String( getClass( vector ) );
        var s:int = c.indexOf( '<' ) + 1;
        var e:int = c.indexOf( '>' );
        return getDefinitionByName( c.substring( s, e ) ) as Class;
    }


private function getIsVector(obj:Object):Boolean
{
    return String(obj.constructor).indexOf('[class Vector.<*>]') == 0;
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号