当前位置:  开发笔记 > 编程语言 > 正文

如何在JavaScript中创建抽象基类?

如何解决《如何在JavaScript中创建抽象基类?》经验,为你挑选了9个好方法。

是否可以在JavaScript中模拟抽象基类?最优雅的方式是什么?

说,我想做一些事情: -

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

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

应输出:'bark','meow'



1> Jordão..:

创建抽象类的一种简单方法是:

/**
 @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();

在这里小提琴(查看控制台输出).


@undefined:了解它我建议你在Javascript中查找原型继承:[this](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain)是一个很好的指南.

2> some..:

你的意思是这样的:

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


@HairOfTheDog是的,你错过了大约五年前回答的问题,当时的javascript没有抽象类,问题是为了模拟**它的方式(`whattosay`没有在*动物中定义*),这个答案清楚地询问提出的答案是否是提问者正在寻找的答案.它没有声称为javascript中的抽象类提供解决方案.提问者没有费心回复我或其他任何人,所以我不知道它是否适合他.我很抱歉,如果一个五岁的人提出的回答别人的问题并不适合你.

3> 小智..:

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.



4> Ian Oxley..:

您可以查看Dean Edwards的基础课程:http://dean.edwards.name/weblog/2006/03/base/

或者,道格拉斯·克罗克福德(Douglas Crockford)就JavaScript中的经典继承提供了这个例子/文章:http://www.crockford.com/javascript/inheritance.html


关于Crockford链接,这是一堆垃圾.他在那篇文章的末尾添加了一个注释:"我现在看到我早期尝试用JavaScript支持经典模型是一个错误."_

5> bobince..:

是否可以在JavaScript中模拟抽象基类?

当然.在JavaScript中有大约一千种方法来实现类/实例系统.这是一个:

// 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!


"var c = function(){...}"将在子类()或其他包含范围的任何内容中创建闭包.可能不重要,但我想保持它可能不需要的父范围; 纯文本Function()构造函数避免了闭包.

6> Leven..:
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! 



7> Georg Schöll..:
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中有效。

如果您不了解它的工作原理,请阅读原型链。


Safari和Chrome使用不同的JavaScript引擎,Safari使用[JavaScriptCore](http://webkit.org/projects/javascript/),而Chrome使用[V8](http://code.google.com/p/ v8 /)。两种浏览器共享的东西是布局引擎[WebKit](http://en.wikipedia.org/wiki/WebKit)。

8> yusufaytas..:

您可以使用对象原型创建抽象类,一个简单的示例可以如下所示:

var SampleInterface = {
   addItem : function(item){}  
}

您可以更改上述方法,实现时可由您自行决定.如需详细观察,您可以访问此处.



9> Maciej Sikor..:

问题已经很老了,但我创建了一些可能的解决方案,如何创建抽象的"类"并阻止创建类型的对象.

//our Abstract class
var Animal=function(){
  
    this.name="Animal";
    this.fullname=this.name;
    
    //check if we have abstract paramater in prototype
    if (Object.getPrototypeOf(this).hasOwnProperty("abstract")){
    
    throw new Error("Can't instantiate abstract class!");
    
    
    }
    

};

//very important - Animal prototype has property abstract
Animal.prototype.abstract=true;

Animal.prototype.hello=function(){

   console.log("Hello from "+this.name);
};

Animal.prototype.fullHello=function(){

   console.log("Hello from "+this.fullname);
};

//first inheritans
var Cat=function(){

	  Animal.call(this);//run constructor of animal
    
    this.name="Cat";
    
    this.fullname=this.fullname+" - "+this.name;

};

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

//second inheritans
var Tiger=function(){

    Cat.call(this);//run constructor of animal
    
    this.name="Tiger";
    
    this.fullname=this.fullname+" - "+this.name;
    
};

Tiger.prototype=Object.create(Cat.prototype);

//cat can be used
console.log("WE CREATE CAT:");
var cat=new Cat();
cat.hello();
cat.fullHello();

//tiger can be used

console.log("WE CREATE TIGER:");
var tiger=new Tiger();
tiger.hello();
tiger.fullHello();


console.log("WE CREATE ANIMAL ( IT IS ABSTRACT ):");
//animal is abstract, cannot be used - see error in console
var animal=new Animal();
animal=animal.fullHello();
推荐阅读
惬听风吟jyy_802
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有