126

JavaScriptで抽象基本クラスをシミュレートすることは可能ですか? それを行う最もエレガントな方法は何ですか?

たとえば、次のようなことをしたい: -

var cat = new Animal('cat');
var dog = new Animal('dog');

cat.say();
dog.say();

次のように出力されます: 'bark', 'meow'

4

17 に答える 17

144

抽象クラスを作成する簡単な方法の 1 つは次のとおりです。

/**
 @constructor
 @abstract
 */
var Animal = function() {
    if (this.constructor === Animal) {
      throw new Error("Can't instantiate abstract class!");
    }
    // Animal initialization...
};

/**
 @abstract
 */
Animal.prototype.say = function() {
    throw new Error("Abstract method!");
}

Animalクラス」とsayメソッドは抽象的です。

インスタンスを作成すると、次のエラーがスローされます。

new Animal(); // throws

これは、そこから「継承」する方法です。

var Cat = function() {
    Animal.apply(this, arguments);
    // Cat initialization...
};
Cat.prototype = Object.create(Animal.prototype);
Cat.prototype.constructor = Cat;

Cat.prototype.say = function() {
    console.log('meow');
}

Dogそれのように見えます。

そして、これはあなたのシナリオがどのように展開されるかです:

var cat = new Cat();
var dog = new Dog();

cat.say();
dog.say();

ここでフィドルします(コンソール出力を見てください)。

于 2014-01-19T18:40:17.273 に答える
116

JavaScript クラスと継承 (ES6)

ES6 によれば、JavaScript クラスと継承を使用して、必要なことを達成できます。

ECMAScript 2015 で導入された JavaScript クラスは、主に、JavaScript の既存のプロトタイプベースの継承に対する構文糖衣です。

参照: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes

まず、抽象クラスを定義します。このクラスはインスタンス化できませんが、拡張できます。これを拡張するすべてのクラスで実装する必要がある関数を定義することもできます。

/**
 * Abstract Class Animal.
 *
 * @class Animal
 */
class Animal {

  constructor() {
    if (this.constructor == Animal) {
      throw new Error("Abstract classes can't be instantiated.");
    }
  }

  say() {
    throw new Error("Method 'say()' must be implemented.");
  }

  eat() {
    console.log("eating");
  }
}

その後、具体的なクラスを作成できます。これらのクラスは、抽象クラスからすべての機能と動作を継承します。

/**
 * Dog.
 *
 * @class Dog
 * @extends {Animal}
 */
class Dog extends Animal {
  say() {
    console.log("bark");
  }
}

/**
 * Cat.
 *
 * @class Cat
 * @extends {Animal}
 */
class Cat extends Animal {
  say() {
    console.log("meow");
  }
}

/**
 * Horse.
 *
 * @class Horse
 * @extends {Animal}
 */
class Horse extends Animal {}

そして結果は…

// RESULTS

new Dog().eat(); // eating
new Cat().eat(); // eating
new Horse().eat(); // eating

new Dog().say(); // bark
new Cat().say(); // meow
new Horse().say(); // Error: Method say() must be implemented.

new Animal(); // Error: Abstract classes can't be instantiated.
于 2018-01-24T17:10:19.557 に答える
28

次のような意味ですか。

function Animal() {
  //Initialization for all Animals
}

//Function and properties shared by all instances of Animal
Animal.prototype.init=function(name){
  this.name=name;
}
Animal.prototype.say=function(){
    alert(this.name + " who is a " + this.type + " says " + this.whattosay);
}
Animal.prototype.type="unknown";

function Cat(name) {
    this.init(name);

    //Make a cat somewhat unique
    var s="";
    for (var i=Math.ceil(Math.random()*7); i>=0; --i) s+="e";
    this.whattosay="Me" + s +"ow";
}
//Function and properties shared by all instances of Cat    
Cat.prototype=new Animal();
Cat.prototype.type="cat";
Cat.prototype.whattosay="meow";


function Dog() {
    //Call init with same arguments as Dog was called with
    this.init.apply(this,arguments);
}

Dog.prototype=new Animal();
Dog.prototype.type="Dog";
Dog.prototype.whattosay="bark";
//Override say.
Dog.prototype.say = function() {
        this.openMouth();
        //Call the original with the exact same arguments
        Animal.prototype.say.apply(this,arguments);
        //or with other arguments
        //Animal.prototype.say.call(this,"some","other","arguments");
        this.closeMouth();
}

Dog.prototype.openMouth=function() {
   //Code
}
Dog.prototype.closeMouth=function() {
   //Code
}

var dog = new Dog("Fido");
var cat1 = new Cat("Dash");
var cat2 = new Cat("Dot");


dog.say(); // Fido the Dog says bark
cat1.say(); //Dash the Cat says M[e]+ow
cat2.say(); //Dot the Cat says M[e]+ow


alert(cat instanceof Cat) // True
alert(cat instanceof Dog) // False
alert(cat instanceof Animal) // True
于 2009-02-28T12:50:28.610 に答える
11

JavaScriptで抽象基本クラスをシミュレートすることは可能ですか?

そうです。JavaScript でクラス/インスタンス システムを実装するには、約 1000 通りの方法があります。ここに1つがあります:

// Classes magic. Define a new class with var C= Object.subclass(isabstract),
// add class members to C.prototype,
// provide optional C.prototype._init() method to initialise from constructor args,
// call base class methods using Base.prototype.call(this, ...).
//
Function.prototype.subclass= function(isabstract) {
    if (isabstract) {
        var c= new Function(
            'if (arguments[0]!==Function.prototype.subclass.FLAG) throw(\'Abstract class may not be constructed\'); '
        );
    } else {
        var c= new Function(
            'if (!(this instanceof arguments.callee)) throw(\'Constructor called without "new"\'); '+
            'if (arguments[0]!==Function.prototype.subclass.FLAG && this._init) this._init.apply(this, arguments); '
        );
    }
    if (this!==Object)
        c.prototype= new this(Function.prototype.subclass.FLAG);
    return c;
}
Function.prototype.subclass.FLAG= new Object();

var cat = new Animal('cat');

もちろん、それは実際には抽象基本クラスではありません。次のような意味ですか。

var Animal= Object.subclass(true); // is abstract
Animal.prototype.say= function() {
    window.alert(this._noise);
};

// concrete classes
var Cat= Animal.subclass();
Cat.prototype._noise= 'meow';
var Dog= Animal.subclass();
Dog.prototype._noise= 'bark';

// usage
var mycat= new Cat();
mycat.say(); // meow!
var mygiraffe= new Animal(); // error!
于 2009-02-28T11:12:45.210 に答える
10
Animal = function () { throw "abstract class!" }
Animal.prototype.name = "This animal";
Animal.prototype.sound = "...";
Animal.prototype.say = function() {
    console.log( this.name + " says: " + this.sound );
}

Cat = function () {
    this.name = "Cat";
    this.sound = "meow";
}

Dog = function() {
    this.name = "Dog";
    this.sound  = "woof";
}

Cat.prototype = Object.create(Animal.prototype);
Dog.prototype = Object.create(Animal.prototype);

new Cat().say();    //Cat says: meow
new Dog().say();    //Dog says: woof 
new Animal().say(); //Uncaught abstract class! 
于 2013-09-18T21:04:31.897 に答える
6

強制したいもう 1 つのことは、抽象クラスがインスタンス化されていないことを確認することです。これを行うには、Abstract クラス コンストラクターとして設定された FLAG として機能する関数を定義します。次に、スローされる例外を含むコンストラクターを呼び出す FLAG の構築を試みます。以下の例:

(function(){

    var FLAG_ABSTRACT = function(__class){

        throw "Error: Trying to instantiate an abstract class:"+__class
    }

    var Class = function (){

        Class.prototype.constructor = new FLAG_ABSTRACT("Class");       
    }

    //will throw exception
    var  foo = new Class();

})()
于 2012-03-07T21:08:05.987 に答える
5
function Animal(type) {
    if (type == "cat") {
        this.__proto__ = Cat.prototype;
    } else if (type == "dog") {
        this.__proto__ = Dog.prototype;
    } else if (type == "fish") {
        this.__proto__ = Fish.prototype;
    }
}
Animal.prototype.say = function() {
    alert("This animal can't speak!");
}

function Cat() {
    // init cat
}
Cat.prototype = new Animal();
Cat.prototype.say = function() {
    alert("Meow!");
}

function Dog() {
    // init dog
}
Dog.prototype = new Animal();
Dog.prototype.say = function() {
    alert("Bark!");
}

function Fish() {
    // init fish
}
Fish.prototype = new Animal();

var newAnimal = new Animal("dog");
newAnimal.say();

これは標準変数ではないため、動作が保証されていません__proto__が、少なくとも Firefox と Safari では動作します。

それがどのように機能するかを理解していない場合は、プロトタイプ チェーンについて読んでください。

于 2009-02-28T09:58:54.667 に答える
3

Javascript は継承を持つことができます。以下の URL を確認してください。

http://www.webreference.com/js/column79/

アンドリュー

于 2009-02-28T09:13:43.700 に答える
2

Factoryこの場合、デザインパターンを使用できます。prototype親のメンバーを継承するためにJavascript を使用します。

親クラスのコンストラクターを定義します。

var Animal = function() {
  this.type = 'animal';
  return this;
}
Animal.prototype.tired = function() {
  console.log('sleeping: zzzZZZ ~');
}

そして、子クラスを作成します。

// These are the child classes
Animal.cat = function() {
  this.type = 'cat';
  this.says = function() {
    console.log('says: meow');
  }
}

次に、子クラスのコンストラクターを定義します。

// Define the child class constructor -- Factory Design Pattern.
Animal.born = function(type) {
  // Inherit all members and methods from parent class,
  // and also keep its own members.
  Animal[type].prototype = new Animal();
  // Square bracket notation can deal with variable object.
  creature = new Animal[type]();
  return creature;
}

試して。

var timmy = Animal.born('cat');
console.log(timmy.type) // cat
timmy.says(); // meow
timmy.tired(); // zzzZZZ~

完全なコーディング例のCodepen リンクは次のとおりです。

于 2017-04-05T14:03:31.387 に答える
1

特に最初の 2 つ ( somejordãoによるもの) のすべての回答は、従来のプロトタイプ ベースの JavaScript コンセプトを使用して質問に明確に回答していると思います。

アニマル クラス コンストラクターが、渡されたパラメーターに従って構造に動作するようにしたいので、これはCreational Patterns、たとえばFactory Patternの基本的な動作と非常によく似ていると思います。

ここでは、そのように機能させるために少しアプローチしました。

var Animal = function(type) {
    this.type=type;
    if(type=='dog')
    {
        return new Dog();
    }
    else if(type=="cat")
    {
        return new Cat();
    }
};

Animal.prototype.whoAreYou=function()
{
    console.log("I am a "+this.type);
}

Animal.prototype.say = function(){
    console.log("Not implemented");
};

var Cat =function () {
    Animal.call(this);
    this.type="cat";
};

Cat.prototype=Object.create(Animal.prototype);
Cat.prototype.constructor = Cat;

Cat.prototype.say=function()
{
    console.log("meow");
}

var Dog =function () {
    Animal.call(this);
    this.type="dog";
};

Dog.prototype=Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

Dog.prototype.say=function()
{
    console.log("bark");
}

var animal=new Animal();

var dog = new Animal('dog');
var cat=new Animal('cat');

animal.whoAreYou(); //I am a undefined
animal.say(); //Not implemented

dog.whoAreYou(); //I am a dog
dog.say(); //bark

cat.whoAreYou(); //I am a cat
cat.say(); //meow

于 2015-02-01T06:04:10.740 に答える
0
/****************************************/
/* version 1                            */
/****************************************/

var Animal = function(params) {
    this.say = function()
    {
        console.log(params);
    }
};
var Cat = function() {
    Animal.call(this, "moes");
};

var Dog = function() {
    Animal.call(this, "vewa");
};


var cat = new Cat();
var dog = new Dog();

cat.say();
dog.say();


/****************************************/
/* version 2                            */
/****************************************/

var Cat = function(params) {
    this.say = function()
    {
        console.log(params);
    }
};

var Dog = function(params) {
    this.say = function()
    {
        console.log(params);
    }
};

var Animal = function(type) {
    var obj;

    var factory = function()
    {
        switch(type)
        {
            case "cat":
                obj = new Cat("bark");
                break;
            case "dog":
                obj = new Dog("meow");
                break;
        }
    }

    var init = function()
    {
        factory();
        return obj;
    }

    return init();
};


var cat = new Animal('cat');
var dog = new Animal('dog');

cat.say();
dog.say();
于 2016-03-18T23:09:44.060 に答える