ホーム >> 左脳Script >> Adobe Flash >> Action Script >> クラス継承の罠 ~overrideの甘い誘い~

クラス継承の罠 ~overrideの甘い誘い~


クラス継承の罠・・・などと大層な題名ですが、言語の仕様ともいえる嵌り方をしたので記事にしてみます。

以下、再現コード。test のインスタンスを new で作成すると・・・

package  
{

    /**
     * ...
     * @author 
     */
    public class test 
    {
        public function test() 
        {
            var b:baseEx    =   new baseEx();
        }
    }
}

internal class base
{
    private var flag:Boolean;
    //
    public function base() 
    {
        trace("base コンストラクタ");
        value   =   true;
        this.value  =   false;
    }
    //
    public function set value(b:Boolean):void 
    {
        trace("base value set:"+b);
        flag    =   b;
    }
    public function get value():Boolean 
    {
        trace("base value get");
        return  flag;
    }
}

internal class baseEx extends base  //  継承
{
    public function baseEx() 
    {
        trace("baseEx コンストラクタ");
    }
    //
    override public function set    value(b:Boolean):void 
    {
        trace("baseEx value set:"+b);
        super.value =   b;  //  スーパークラスに処理を投げる
    }
    override public function get    value():Boolean 
    {
        trace("baseEx value get");
        return  super.value;    //  スーパークラスに処理を投げる
    }
}

コーディングする者の意図としては、単純に、
  1. base コンストラクタ
  2. base value set:true
  3. base value set:false
  4. baseEx コンストラクタ
という順になると予想するのですが・・・

実際には、以下のような結果となります。

base コンストラクタ
baseEx value set:true
base value set:true
baseEx value set:false
base value set:false
baseEx コンストラクタ
何故か、スーパークラスからサブクラスのセッターに処理が移るという現象。

get 、set で作ったプロパティに関わらず、関数でもスーパークラスとサブクラスで同じ名前の関数を使用すると、このような動作をすることになります。

上記の例にある base は、value という真偽値のプロパティを実装しています。baseEx は、base を継承した上で、同じ名前のプロパティをオーバーライドで実装し、処理をスーパークラスに投げる形になっています。
base のコンストラクタ内で、value プロパティに値を設定しています。ここで、スーパークラスからサブクラスへの参照情報などが全く無い状態であるにも関わらず、サブクラスの処理が実行されるのは何故なのでしょうか。


Action Script では、変数、インスタンスから、クラスの関数に至るまで、全てオブジェクトとして管理されています。プロトタイプベースだとか、プロトタイプ継承だとか言われているようです。
ここで私は「クラスのプロトタイプ、もしくはインスタンスにはクラス継承のスコープのような物が存在しないので、同名の関数があれば優先度の高いサブクラス側が先に処理されるのでは?」と考えました。


・・・しかし、今の私のつたない知識と経験(Action Script 暦?)では、これを検証する方法が思いつきませんでした。Action Script の言語としての仕様を調べたところで、それは仕様書を読んだ事にしかならない訳で・・・


とにかく、結果から考えうるコトは、 「クラスのスコープのようなモノ」が無ければ、オーバーライドとしての動作は至極当然の動作なのですが、C++でのクラスには無い動作(そもそもスーパークラスがサブクラスの関数を参照するコトは基本的に無い)なので、C++のつもりでクラス設計をして嵌ってしまった、と考えました。


つまり、override でスーパークラスと同名の関数を実装する場合、スーパークラスからの参照に気を付けないといけない、という事です。
しかし、何時でもスーパークラスのコードを確認出来るとは限りません。OOとかOOPとか言ってるならなおさらです。スーパークラスのコードなんてカプセル化の名分で隠蔽されているコトを前提に継承&設計しなければなりません。

下手に override を使うと、意図しないスーパークラスからの参照で、動作を追えなくなる可能性もあります。override の使用には注意が必要です。


極論ですが、プロトタイプ型言語でのオブジェクト指向において、override の存在に"思想としての矛盾"を感じてしまうのですが、皆さんはイカがでしょうか?


思想とかなんとかまでくると、もう哲学ですね。
突き詰めるコト自体に、なんの生産性も見出せませんね。


纏めると「override には気をつけろ。」と言う事で。




トラックバック(0)

トラックバックURL: http://n-yagi.0r2.net/sanoupulurun/mt-tb.cgi/45

コメントする

ホーム >> 左脳Script >> Adobe Flash >> Action Script >> クラス継承の罠 ~overrideの甘い誘い~

アーカイブ

このブログ記事について

このページは、n-yagiが2009年5月 6日 20:07に書いたブログ記事です。

ひとつ前のブログ記事は「Google ウェブマスター ツール(その後」です。

次のブログ記事は「TextFieldAutoSize ~オートコンプリートとのすれ違いの果てに」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

Creative Commons License
このブログはクリエイティブ・コモンズでライセンスされています。