kagamihogeの日記

kagamihogeの日記です。

Flex の XML と flash.utils.describeType

ActionScript 3.0 には XML リテラルなるものがあり、ソースコード中にいきなり XML の定義が出来てしまう。

var employees:XML =
    <employees>
<employee ssn="123-123-1234">
<name first="John" last="Doe"/>
    <address>
        <street>11 Main St.</street>
        <city>San Francisco</city>
        <state>CA</state>
        <zip>98765</zip>
    </address>
</employee>
<employee ssn="789-789-7890">
    <name first="Mary" last="Roe"/>
        <address>
        <street>99 Broad St.</street>
        <city>Newton</city>
        <state>MA</state>
        <zip>01234</zip>
    </address>
</employee>
    </employees>;

XML - ActionScript 3.0 言語およびコンポーネントリファレンス の例そのまんまだけども。なんつーかこう、スゲー柔軟だなぁと衝撃を受けました。

更に驚いたのが、ECMAScript for XML(E4X)なるものにも対応していること。こいつは何者かっていうと、こんな感じにラクに XML を扱えるようにしてくれるもの。

trace(employees.employee[0].address.zip);   // 98765
trace(employees.employee[1].@ssn);          // 789-789-7890

XML のノードには "."で、属性には "@" でアクセスができる。いやなんつーかこんなにお手軽に XML 扱えていいのか、ってぐらい驚きました。


でまぁ、これだけだと「ふーん」なんですが。Flex のライブラリに flash.utils.describeType() というものがあります。こいつは何者かというと、いわゆるリフレクション。ただ、結果を XML で返してくれるところがおもしろい。

試しにこんなコードを実行してみると、

var x:XML = flash.utils.describeType(String);
trace(x.toXMLString());

こんな感じの結果が返ってくる。

<type name="String" base="Class" isDynamic="true" isFinal="true" isStatic="true">
  <extendsClass type="Class"/>
  <extendsClass type="Object"/>
  <constant name="length" type="int"/>
  <accessor name="prototype" access="readonly" type="*" declaredBy="Class"/>
  <factory type="String">
    <extendsClass type="Object"/>
    <constructor>
      <parameter index="1" type="*" optional="true"/>
    </constructor>
    <accessor name="length" access="readonly" type="int" declaredBy="String"/>
  </factory>
</type>

とまぁ、クラスの情報を色々と見ることができる。public なメソッドが見れて無いけど String は特別扱いなのかねぇ……

で、コレを上手いこと使ってやると面白いことができる。具体的には MXML と ActionScript の分離。画面デザインとロジックの分割テクニック | デベロッパーセンター で紹介されてる ViewHelper は describeType を使ってクラスの情報を取得して、イベントハンドラとイベントを命名規則で結び付けてます。いわゆる CoC ってヤツですな。

となると気になるのは yui-frameworks ですが、これもやっぱり同じことをやっていました。org.seasar.akabana.yui.core.reflection.ClassRef を覗いてみると、

public function ClassRef( clazz:Class ){
    var describeTypeXml:XML = flash.utils.describeType(clazz);
    concreteClass = clazz;
    super( describeTypeXml );
           
    assembleMetadataRef(describeTypeXml.factory[0]);
    assembleConstructor(describeTypeXml.factory[0]);
    assemblePropertyRef(describeTypeXml.factory[0]);         
    assembleFunctionRef(describeTypeXml.factory[0]);
   assembleInterfaces(describeTypeXml.factory[0]);
    assemblePackage( describeTypeXml );            
    assembleThis( describeTypeXml );
}

こんな感じ。assemble* でクラス表現の XML の各要素を走査してクラスの情報を組み立ててました。

ActionScript は中々面白いですなー。