基底クラスのコンストラクタを呼び出す ― 2005年12月05日 00時06分
「【JavaScript】多重に派生されたクラスのコンストラクタで,基底クラスのコンストラクタを呼び出す方法」(Graviness Blog) にて基底クラスのコンストラクタを呼び出すという話題が出ていた。優乃さんは this
から基底クラスのコンストラクタを呼び出したいようだが、JavaScript では this
が何をさすかは文脈により異なってくる (「ECMAScript における this の意味」(Noncommutative Field) を参照)。なので個人的には基底クラスに関する操作はインスタンス (this
) よりもクラス (コンストラクタ関数) から行ったほうがいいと思う。クラス名に依存したくないなら arguments.callee
を用いればよい。
function Animal() {} // 基底クラス
function Dog() {
this.__super__(); // this が何であるか (this.__super__ が何をさすか) は不定
}
function Cat() {
Cat._superClass.apply(this); // クラス名に依存
}
function Swallow() {
arguments.callee._superClass.apply(this); // クラス名に非依存、でもちょっと長い?
}
しかし実際に書き比べてみるとやはり this
から呼び出せたほうが見通しがいいわけで。this
から呼び出す際の問題は基底クラスのコンストラクタ内でも this.__super__
が変わらず、それ以上上のクラスのコンストラクタを呼び出せないこと。ならば基底クラスのコンストラクタを呼び出すときだけ __super__
を書き換えてやればいいのではないか。こんな感じで。
function inherit(subClass, superClass) {
var Temp = new Function();
Temp.prototype = superClass.prototype;
subClass.prototype = new Temp;
subClass.prototype.constructor = subClass;
subClass.prototype.__super__ = function () {
var originalSuper = this.__super__;
this.__super__ = superClass.prototype.__super__ || null;
superClass.apply(this, arguments);
if (this.constructor == subClass)
delete this.__super__;
else
this.__super__ = originalSuper;
};
}
個人的に Class.prototype.constructor == Class
というのは常に成り立っていてほしいのでそのように修正。基底クラスのコンストラクタ内で this.method()
としても SuperClass#method
ではなく SubClass#method
が呼び出されるなどの不具合はあるが、コンストラクタ関数だけで完結する処理ならこれでうまく行くと思う。
function SuperSuperClass() {
alert("SuperSuperClass Constructor");
this.p = "supersuperclass";
}
function SuperClass() {
alert("SuperClass Constructor");
this.__super__(); // SuperSuperClass のコンストラクタを呼び出す.
this.q = "superclass";
}
function SubClass() {
alert("SubClass Constructor");
this.__super__(); // SuperClass のコンストラクタを呼び出す.
this.r = "subclass";
}
// 継承
inherit(SuperClass, SuperSuperClass);
inherit(SubClass, SuperClass);
var a = new SubClass();
alert(a.p); // "supersuperclass"
alert(a.q); // "superclass"
alert(a.r); // "subclass"
コメント
トラックバック
このエントリのトラックバックURL: http://nanto.asablo.jp/blog/2005/12/05/166280/tb
_ JavaScriptっぽい。 - 2005年12月08日 22時18分
【JavaScript】多重に派生されたクラスのコンストラクタで,基底クラスのコンストラクタを呼び出す方法。
なぜ2番目のコードでダメかというと、prototypeを書き換えれば、当然constructorもprot
_ Graviness Blog - 2005年12月11日 16時19分
0. 多重に派生されたクラスのコンストラクタで,基底クラスのコンストラクタを呼び出す方法@Graviness Blog
1. 基底クラスのコンストラクタを呼び出す@Days on the Moon
2. 継承元のコンストラクタを順々に呼び出す。@JavaScriptっぽい。
3. 基底クラスコンストラクタ呼び出しの落とし穴@Days on the Moon
nanto_viさん,PURESTさんありがとう!
さて,上記一連の記事を読んでもらうと分かりますが,以下の方法が良いと判断しました.このコードは達人でもなかなか書けない代物ですよ!凄い!/**
* 継承関数.
* @param subClass 派生クラス
* @param superClass 基底クラス
*/
function inherit(subClass, superClass) {
    var Temp = new Function();
    Temp.prototype = superClass.prototype;
    subClass.prototype = new Temp;
    subClass.prototype.constructor = subClass;
    subClass.prototype.__super__ = function () {
        var originalSuper = this.__super__;
        this.__super__ = superClass.prototype.__super__ || null;
        superClass.apply(this, arguments);
        if (this.constructor == subClass)
            delete this.__super__;
        else
            this.__super__ = originalSuper;
    };
}
function SuperSuperClass() {
    alert(\"SuperSuperClass Constructor\");
    this.p = \"supersuperclass\";
}
function SuperClass() {
    alert(\"SuperClass Constructor\");
    this.__super__(); // SuperSuperClassのコンストラクタを呼び出す.
    this.q = \"superclass\";
}
function SubClass() {
    alert(\"SubClass Constructor\");
    this.__super__(); // SuperClassのコンストラクタを呼び出す.
    this.r = \"subclass\";
}
// 継承
inherit(SuperClass, SuperSuperClass);
inherit(SubClass, SuperClass);
コメントをどうぞ
※メールアドレスとURLの入力は必須ではありません。 入力されたメールアドレスは記事に反映されず、ブログの管理者のみが参照できます。
※投稿には管理者が設定した質問に答える必要があります。