JScript.NET  新JavaScript入門  JavaScript,Neo-Generation  DOM  WSH  掲示板  表紙
名前空間とライブラリ  抽象クラスとインターフェイス 
Written 9/20/03
JScript.NET
継承
継承
継承という機構は、主に既存のコードを再利用するためにあります。 誰かが立派なクラスを作っていれば、それにちょちょいと追加してやればいいんです。 ただ、そんなに立派なものでなければコピペという手もあるわけで。 あんまり使いすぎるのもどうかと思います。
そんなことはおいといて、JScript.NETでは、 ベースとなるクラスを基本クラス、 そこから作られるクラスを派生クラスと呼びます。
ここでは、本クラスとそこから派生するコミッククラスを例に考えましょう。 コミックには背表紙に各出版社独自のコードが書かれています。 このコードをプロパティとして追加し、 ToStringメソッドもこのコードを追加するように書き替えましょう。
    comic1.js
    -------------------------------------------------------------------
    var book1 : CBook = new CBook("離散系の数学");
    var comic1 : CComic = new CComic("お月様のことばかり", "KCN862");
    print(book1.ToString());
    print(comic1.ToString());
    
    class CBook {
        var title : String;
        function CBook(str : String) {
            title = str;
        }
        function ToString() : String {
            return title;
        }
    }
    
    class CComic extends CBook {
        var code : String;
        function CComic(str1 : String, str2 : String) {
            super(str1);
            code = str2;
        }
        function ToString() : String {
            return code + " " + title;
        }
    }
 
これを実行すると次のようになります。
    >comic1
    離散系の数学
    KCN862 お月様のことばかり
 
クラスを継承するには、 次のようにextendsをつけてクラスを定義します。
    //基本クラス
    class CBook {
        ...
    }
    
    //派生クラス
    class CComic extends CBook {
        ...
    }
 
次のようにクラスをfinalで修飾すると 継承できなくなります。
    //継承できないクラス
    final class CBook {
        ...
    }
    
    //型 : 'CBook' を拡張できません。
    class CComic extends CBook {
        ...
    }
 
継承で一つうれしいのは、 派生クラスのインスタンスも基本クラスのと一括で扱えることです。 今のクラスを利用して、
    comic2.js
    -------------------------------------------------------------------
    //同じ配列に入れて
    var books : CBook[] = new CBook[2];
    books[0] = new CBook("離散系の数学");
    books[1] = new CComic("お月様のことばかり", "KCN862");
    
    //まとめて処理
    for(var i = 0; i < 2; i++)
        print(books[i].ToString());
        ...
 
とすると上と同じ結果が得られます。
コンストラクタ
派生クラスの中でコンストラクタは次のようにしています。
    class CComic extends CBook {
            ...
        function CComic(str1 : String, str2 : String) {
            super(str1);
            code = str2;
        }
            ...
    }
 
このsuperは 基本クラスのコンストラクタを呼び出しています。
ここでは、
    title = str1;
 
としても同じなのですが、もっと複雑なときは有効になるでしょう。
オーバーライド
上の例ではToStringというメソッドが派生クラスでは再定義されていました。
    class CBook {
            ...
        function ToString() : String {
            return title;
        }
    }
    
    class CComic extends CBook {
            ...
        function ToString() : String {
            return code + " " + title;
        }
    }
 
こういうのは再定義ではなくオーバーライドといいます。 これを実行すると、
    >comic2
    離散系の数学
    KCN862 お月様のことばかり
 
となったので、CBookのToStringのメソッドではなく、 CComicのToStringメソッドを使っています。 すなわち、ToStringメソッドを置き替えていることになります。 オーバーライドを次のように修飾子を用いて明示することもできます。
    class CComic extends CBook {
            ...
        override function ToString() : String {
            return code + " " + title;
        }
    }
 
逆に置き替えないようにするにはhide修飾子を用います。
    class CComic extends CBook {
            ...
        hide function ToString() : String {
            return code + " " + title;
        }
    }
 
こうすると、
    離散系の数学
    お月様のことばかり
 
となります。
逆に基本クラスでfinal修飾子を指定すると オーバーライドできなくなります。
    class CBook {
            ...
        final function ToString() : String {
            return title;
        }
    }
    
    class CComic extends CBook {
            ...
        function ToString() : String {
            return code + " " + title;
        }
    }
 
これでも同じことになります。
このときoverrideを使うとコンパイルエラーになります。
protected
メンバにprotected修飾子をつけると、 継承したクラスからのみアクセスできるようになります。
    var d : CDerived = new CDerived();
    print(d.method2());      //OK
    var b : CBase = new CBase();
    print(b.method1());      //エラー
    
    //基本クラス
    class CBase {
        function CBase() { }
        protected function method1() : String {
            return "Base";
        }
    }
    
    //派生クラス
    class CDerived {
        function CDerived() { }
        function method2() : String {
            return super.method1();    //superで基本クラスにアクセス
        }
    }
 
多重継承
多重継承はできないようです。
ただし、インターフェイスは多重継承できます
prev, next, exit