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を作って評価系の静的メソッドを作っておけば何とかなるかも。

Trackback

http://memo.kappa-lab.com/mt-tb.cgi/285

Comment (2)

通りすがり : 2009 .04 .04

if (Object(this) == Hoge) throw new Error("で判定したらどうですか?");

ついでに、コンパイラ時にエラーを吐くようにするなら、


package
{
public class Hoge
{
public function Hoge(permit:Permit)
{
if (Object(this) == Hoge) throw new Error("抽象クラスですよ。");
}
protected function getPermit():Permit
{
return new Permit();
}
}
}
class Permit {}

という感じにして、実装クラスでsuper.getPermit()の戻り値を渡してもらうとか。
(少し面倒ですが。)

とおりすがり : 2009 .04 .04

先ほどのコードの一部が間違えておりました。
正しくは、


if (Object(this).prototype.constructor !== Hoge)

です。

Leave your comment :

(いままで、ここでコメントしたことがないときは、コメントを表示する前に承認が必要になることがあります。そのときはしばらくお待ちください。)




RSS + Contuct

  • rss
  • email

Credit

Copyright (C) 2007 kappa-lab.com.
All Rights Reserved.