イベントクラスを定義する

EventDispatcher.dispatchEvent() で発行するイベントオブジェクトのクラスを定義すると、より厳密なイベントの管理が可能になる。

例えば、「車が走った」というイベントを考える。この場合、イベントオブジェクトのイベントソースは車で、イベントタイプは "onMove" となる。また、属性として、イベントが発生した瞬間の位置情報 (x,y) を持たせる。まず、従来の Object 型を使ったパターンを見てみる。

Object 型のイベントオブジェクトを使用したパターン

車クラスの move() メソッドでイベントを発行する。target 属性は省略が可能 (EventDispatcher が割り当ててくれる)。

class Car extends EventDispatcher {
//コンストラクタなど
/**
*  移動する
*/
public function move():Void {
//イベントを発行する
var event:Object = new Object();
event.type = "onMove";
event.x = this.x;
event.y = this.y;
this.dispatchEvent(event);
}
}

クライアントは車の移動イベントをリスンする。

private function myCarMove(event:Object):Void {
trace([event.x, event.y] + "から移動した");
}
this.myCar.addEventListener("onMove", Delegate.create(this, myCarMove));

このパターンを、イベントクラスを用いたものに変更する。まず、基底クラスとなる Event クラスを定義する。

Event クラス

class Event {
public var target:Object;
public var type:String;
/**
*  コンストラクタ
*  @param type イベントタイプ
*/
public function Event(type:String) {
this.type = type;
}
}

EventDispatcher が書き換えるフィールド (target と type) は public にする。

次に、この Event クラスを継承した MoveEvent クラスを定義する。

MoveEvent クラス

class MoveEvent extends Event {
public static var MOVE:String = "onMove";
private var x:Number;
private var y:Number;
/**
*  コンストラクタ
*  @param x x座標
*  @param y y座標
*/
public function MoveEvent(x:Number, y:Number) {
super(MoveEvent.MOVE);
this.x = x;
this.y = y;
}
/**
*  x座標を得る
*  @return x座標
*/
public function getX():Number {
return this.x;
}
/**
*  y座標を得る
*  @return y座標
*/
public function getY():Number {
return this.y;
}
}

位置情報をコンストラクタで与えている。イベントタイプを定数 MoveEvent.MOVE にして、リスナを作成する際には "onMove" という文字列ではなく、MoveEvent.MOVE を指定する。

では、先ほどの車の例を、このクラスを用いたものに書き換えてみる。

MoveEvent 型のイベントオブジェクトを使用したパターン

車クラスの move() メソッドでイベントを発行する。

class Car extends EventDispatcher {
//コンストラクタなど
/**
*  移動する
*/
public function move():Void {
//イベントを発行する
var event:MoveEvent = new MoveEvent(this.x, this.y);
this.dispatchEvent(event);
}
}

クライアントは車の移動イベントをリスンする。

private function myCarMove(event:MoveEvent):Void {
trace([event.getX(), event.getY()] + "から移動した");
}
this.myCar.addEventListener(MoveEvent.MOVE, Delegate.create(this, myCarMove));

いくつかのハードコードしていた文字列が無くなり、Object 型のイベントオブジェクトを使用したパターンよりも、すっきりしたコードになる。また、イベントオブジェクトがカプセル化され、より安全な設計になったと言える。

今回のイベントクラスの設計は、ActionScript 3.0 のイベントパッケージを参考にした。