0

OK、JavaScript OOP で継承を実装するために、ほとんどの手法を修正しました。Java プログラマーとして、私は古典的なアプローチに興味がありますが、ここに問題があります。次のようなクラスを作成したいとしますAnimal(実際のクラスではないことはわかっていますが、この用語を使用させてください)。

function Animal(name){  
    this.name = name;
}
Animal.prototype.getName = function() {
    return this.name;
}

これは私の最初の意図では具体的なクラスであることに注意することが重要です。スーパークラスとして使用するだけでなく、インスタンス化したいと考えています。Animalそれぞれ独自の名前を持つ 複数のインスタンスを作成する場合があります。

このクラスを拡張する方法として、次の方法があります。

function Cat(name, owner) {
    this.name = name;
    this.owner = owner;
}
// ALTERNATIVE 1:
    Cat.prototype = Object.create(Animal.prototype);
// ALTERNATIVE 2: 
    Cat.prototype = new Animal('LOLA');
// END OF ALTERNATIVES
Cat.constructor.prototype = Cat;
Cat.prototype.jump = function() {
    alert(this.name + " jumping");
}

ALTERNATIVE 1では、スーパークラスのメソッドを継承するだけで、実際にnameは Cat でプロパティを再定義する必要があります。ALTERNATIVE 2では、実際には何も変更されません。チェーン内に、nameまったく役に立たないプロパティを保持するオブジェクトがもう 1 つあるだけです。それはすべてのCatインスタンスで同じです。

ここでのポイントはAnimal、独自の名前でクラスを作成し、それを拡張するとすぐに破棄するということです。Animal私が望んでいるのは、プロパティとメソッドの両方を継承する方法であり、何よりも、コンストラクターを再利用できるようにしたいと考えています。

4

1 に答える 1

0

基本コンストラクターのプロパティを継承する従来の方法は次のとおりです。

function Cat(name, owner) {
    Animal.call(this, name); // call the base constructor
    this.owner = owner;
}

Cat.prototype = new Animal;
Cat.prototype.constructor = Cat;
Cat.prototype.jump = function () {
    alert(this.name + " jumping");
};

上記のコードは、他の言語の次のクラスと同等です。

class Cat extends Animal {
    constructor(name, owner) {
        super(name);
        this.owner = owner;
    }

    jump() {
        alert(this.name + " jumping");
    }
}

new Animalプロパティを継承する新しい方法はまったく同じですが、に置き換えるだけObject.create(Animal.prototype)です。新しい方法を好む理由は次のとおりです。

  1. 呼び出しnew Animalは不要なオーバーヘッドです。Catとにかく、コンストラクターはそれを再度呼び出します。
  2. 呼び出しnew Animalで空のオブジェクトが返されない場合があります。オブジェクトにいくつかのプロパティを追加する場合があります。
  3. どの引数を呼び出すかはまだわかりnew Animalません。したがって、それを呼び出す意味はありません。

したがって、継承の好ましい方法は次のとおりです。

function Cat(name, owner) {
    Animal.call(this, name); // call the base constructor
    this.owner = owner;
}

Cat.prototype = Object.create(Animal.prototype);
Cat.prototype.constructor = Cat;
Cat.prototype.jump = function () {
    alert(this.name + " jumping");
};

インスタンスが正しく動作するために必要な初期化を実行する可能性があるため、基本コンストラクターを呼び出すことが重要であることに注意してください。

古典的なスタイルで JavaScript コードを書くことに興味がある場合は、プロトタイプ クラスの同形性について説明している次の回答をご覧ください。上記の回答から取得した次のコード:

function CLASS(prototype, base) {
    switch (typeof base) {
    case "function": base = base.prototype;
    case "object": prototype = Object.create(base, descriptorOf(prototype));
    }

    var constructor = prototype.constructor;
    constructor.prototype = prototype;
    return constructor;
}

function descriptorOf(object) {
    return Object.keys(object).reduce(function (descriptor, key) {
        descriptor[key] = Object.getOwnPropertyDescriptor(object, key);
        return descriptor;
    }, {});
}

関数を使用して、CLASS次のように JavaScript で疑似クラスを定義できます。

var Animal = CLASS({
    constructor: function (name) {
        this.name = name;
    },
    getName: function () {
        return this.name;
    }
});

var Cat = CLASS({
    constructor: function (name, owner) {
        Animal.call(this, name);
        this.owner = owner;
    },
    jump: function () {
        alert(this.name + " jumping");
    }
}, Animal);

JavaScript で継承を行う方法は他にもあります。JavaScript の継承について理解を深めるために、 Why Prototypal Inheritance Matters に関する私のブログ記事を読むことをお勧めします。

于 2013-08-14T01:34:00.387 に答える