AS3で抽象クラスを泥臭く作る
AS3ではインターフェイスを定義できるもののアブストラクトクラス(抽象クラス)できない。この問題に関してはビンタ先生も「PHPが羨ましいのは抽象クラスをてきぎできるところ(だけ)」とtwitterで言ってた気がする。(間違ってたらごめんね。)
ところが、DisplayObjectなんかは間違いなく抽象クラスだし、ASDocを読んでも「このクラスは基本抽象クラスだからnewすんなyo!」とか書いてあります。
ビルトインクラスで可能なんだから、カスタムクラスでもできるんじゃないかと思って、少し考えてみたところ、泥臭いながら定義できるようになりました。
さらに泥臭いながらも抽象メソッドも定義してみました。
具体的には
1.抽象クラスのコンストラクタでgetQualifiedClassName()を使って完全修飾名から抽象クラスかサブクラスかを判断。抽象クラスならエラーを吐く。
2.抽象メソッド内にArgumentErrorを生成。抽象クラスのコンストラクタ内で実行。サブクラス内でオーバーライドしておかないとエラーを吐く。
という方法でやってます。
以下、サンプルです。
抽象クラスpackage abstractClassTest { import flash.utils.getQualifiedClassName; public class AbstractClass { public function AbstractClass() { //直接newされるとエラーをはく if (getQualifiedClassName(this) == "abstractClassTest::AbstractClass"){ throw new ArgumentError( "abstractClassTest::AbstractClass is abstruct Class"); } //オーバーライドされていないとエラーをはく //ただし無駄にメソッドがコールされるので、駄目か。 hoo() ; } /*abstact method*/ public function hoo():void { //オーバーライドされていないとエラーをはく throw new ArgumentError("hoo() is abstruct method. you must implement! "); } } }具象クラス
package abstractClassTest { public class ConcreteClass extends AbstractClass { public function ConcreteClass() { } override public function hoo():void { trace("実装しました") } } }実装忘れクラス
package abstractClassTest { public class WarningConcreteClass extends AbstractClass { //抽象メソッドを実装し忘れてみる public function WarningConcreteClass() { } } }クライアントプログラム
package abstractClassTest { import flash.display.Sprite; public class Main extends Sprite { public function Main() { //OK var c:AbstractClass = new ConcreteClass(); c.hoo();//"実装しました //Error new WarningConcreteClass(); //Error new AbstractClass() } } }
追記:
自分的には大発明のつもりだったけど、http://un-q.net/のll_koba_llさんに、「コンストラクタで無駄にメソッドをコールしちゃだめじゃん」と突っ込まれました。
いや、ほんとその通り。
describeType()を使えば評価できそうな気もするけど、それはまた今度やります。
多分AbstactClassUtilを作って評価系の静的メソッドを作っておけば何とかなるかも。
自分的には大発明のつもりだったけど、http://un-q.net/のll_koba_llさんに、「コンストラクタで無駄にメソッドをコールしちゃだめじゃん」と突っ込まれました。
いや、ほんとその通り。
describeType()を使えば評価できそうな気もするけど、それはまた今度やります。
多分AbstactClassUtilを作って評価系の静的メソッドを作っておけば何とかなるかも。
Comment (2)
通りすがり : 2009 .04 .04
ついでに、コンパイラ時にエラーを吐くようにするなら、
という感じにして、実装クラスでsuper.getPermit()の戻り値を渡してもらうとか。
(少し面倒ですが。)
とおりすがり : 2009 .04 .04
先ほどのコードの一部が間違えておりました。
正しくは、