getter/setterを利用してイベントリスナーを動的に切り替える
AS2では
Mouse.addListener(this);
とすることで、MouseDown時に、this.onMouseDownメソッドが呼ばれるようになります。
trace("default");
}
function test() {
trace("test");
}
Mouse.addListener(this);
this.onMouseDown = test;
などとすることで、addListenerした後でもonMouseDownメソッドを動的に切り替えることができます。
AS3で採用されたイベントモデルでは、addEventLisntener時にイベントリスナーの参照を引数として指定するようになり、また、ほかのモダンな言語と同様、参照渡し(call by reference)ができないため、以下のようなコードではAS2に相当する動的なリスナーの切り替えができません。
trace("default");
}
function test(event:MouseEvent):void {
trace("test");
}
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
onMouseDown = test; //意味なし
上記の例では、addEventListenerで渡されるのは、その時点でのonMouseDownの値なので、その後にonMouseDownの値を変えても意味がありません。
【参考】AS3では関数の引数はすべて値渡し(call by value)である
そこで、下記のようにgetter/setterメソッドを利用することで同じような動作が実現できます。
この例では、最初のMouseDownと2回目以降のMouseDownで呼ばれるリスナー関数が切り替わります。
import flash.display.Sprite;
import flash.events.MouseEvent;
public class DynamicListenerSample extends Sprite {
private var _onMouseDown:Function;
private function onMouseDownHandler(event:MouseEvent):void {
if (_onMouseDown!=null) _onMouseDown(event);
};
private function get onMouseDown():Function {
return onMouseDownHandler;
}
private function set onMouseDown(func:Function):void {
_onMouseDown = func;
}
public function DynamicListenerSample() {
onMouseDown = test;
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
}
private function test(event:MouseEvent):void {
trace("This is test.");
onMouseDown = test2;
}
private function test2(event:MouseEvent):void {
trace("This is test2.");
stage.removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
}
}
}
▼出力結果
This is test. ←1回目のMouseDown
This is test2. ←2回目のMouseDown
(3回目以降は呼ばれない)
(追記)
getterで無名関数を返すようにしていましたが、そうするとremoveEventListenerでも新たに無名関数が作られてしまいremoveEventListenerできなくなるので、上記のとおり修正しました。