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
if (Object(this) == Hoge) throw new Error("で判定したらどうですか?");ついでに、コンパイラ時にエラーを吐くようにするなら、
という感じにして、実装クラスでsuper.getPermit()の戻り値を渡してもらうとか。
(少し面倒ですが。)
とおりすがり : 2009 .04 .04
先ほどのコードの一部が間違えておりました。
正しくは、