ActionScript 3 で Vector クラスの配列を動的に生成するには

オブジェクトのシリアライズに関する実装をする上で、Vector クラスのリフレクションはできるのか調べてみた。

Vectorクラス名を取得

var classInfo:Object = ObjectUtil.getClassInfo(Vector.<Entity>);
trace(classInfo.name);

とすると出力は下記のようになった。

__AS3__.vec::Vector.<com.tilfin.sample::Entity>

こんどは、getDefinitionByName を使って生成してみると

var cls:Class = getDefinitionByName("__AS3__.vec::Vector.<com.tilfin.sample::Entity>") as Class
var vector:Vector.<Entity> = new cls();

もちゃんと上手くいった。ということで色々できそうです。

Vectorユーティリティクラス

サンプルとして試しに書いてみた。

package
{
  import flash.utils.getDefinitionByName;
  import flash.utils.getQualifiedClassName;

  public class VectorUtil
  {
    /**
     * 指定されたオブジェクトをエレメントとするVectorクラスの配列を返します。
     * 
     * @param args 1つ以上のオブジェクトもしくは配列
     * @return Vectorインスタンス
     * 
     */
    public static function toVector(...args):* {
      var item:*;
      var items:Array;
      if (args.length == 1) {
        item = args[0];
        if (item is Array) {
          items = item as Array;
        } else {
          items = [ item ];
        }
      } else {
        items = args as Array;
      }
      
      if (!items || items.length == 0) {
        throw new ArgumentError("requires at least one argument.");
      }

      item = items.shift();
      var vectorClass:Class = getVectorClass(item);
      var vector:* = new vectorClass();
      
      vector.push(item);
      for each (var i:* in items) {
        vector.push(i);
      }
      
      return vector;
    }
    
    /**
     * 指定されたオブジェクトクラスを格納するVectorクラスオブジェクトを返します。
     * 
     * @param value 完全修飾クラス名が必要なオブジェクト
     * @return Vectorクラスオブジェクト
     * 
     */
    public static function getVectorClass(value:*):Class {
      var className:String;
      if (value is String) {
        className = value;
      } else {
        className = getQualifiedClassName(value);
      }
      return getDefinitionByName("__AS3__.vec::Vector.<" + className + ">") as Class;
    }
  }
}

下記のエンティティクラスを使って例を実行してみた。

package com.tilfin.sample
{
  public class Entity
  {
    private var _name:String;

    public function Entity(name:String) {
      _name = name;
    }

    public function get name():String {
      return _name;
    }
  }
}
import com.tilfin.sample.Entity;

private function sample():void {
  var et1:Entity = new Entity("sample1");
  var et2:Entity = new Entity("sample2");

  var vector:Vector.<Entity> = VectorUtil.toVector(et1, et2);
  for each (var item:Entity in vector) {
    trace(item.name);
  }
}

こんなかんじに書くと、下記のように出力される。

sample1
sample2

なお、Vector クラスは Flash Player 10 もしくは AIR 1.5 以降が必須です。