ฉันจะสร้างคลาสพื้นฐานนามธรรมใน JavaScript ได้อย่างไร


109

เป็นไปได้ไหมที่จะจำลองคลาสพื้นฐานแบบนามธรรมใน JavaScript วิธีที่สง่างามที่สุดที่จะทำคืออะไร?

พูดว่าฉันต้องการทำสิ่งที่ชอบ: -

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

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

ควรส่งออก: 'bark', 'meow'


คำตอบ:


127

วิธีง่ายๆอย่างหนึ่งในการสร้างคลาสนามธรรมคือ:

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

Fiddle ที่นี่ (ดูที่เอาต์พุตคอนโซล)


คุณช่วยอธิบายทีละบรรทัดได้ไหมถ้าคุณไม่รังเกียจเพราะฉันยังใหม่กับ OOP ขอบคุณ!
React Developer

2
@undefined: เพื่อให้เข้าใจฉันขอแนะนำให้คุณค้นหาการสืบทอดต้นแบบใน Javascript: นี่เป็นคำแนะนำที่ดี
Jordão

ขอบคุณสำหรับการตอบกลับ .. จะผ่านลิงค์
ตอบสนองผู้พัฒนา

ส่วนที่สำคัญที่สุดคือในข้อมูลโค้ดแรกมีข้อผิดพลาดเกิดขึ้น นอกจากนี้คุณยังอาจส่งคำเตือนหรือส่งคืนค่าว่างแทนวัตถุเพื่อดำเนินการแอปพลิเคชันต่อไปทั้งนี้ขึ้นอยู่กับการใช้งานของคุณ ในความคิดของฉันนี่เป็นวิธีที่ถูกต้องในการใช้ "คลาส" JS แบบนามธรรม
dudewad

1
@ G1P: นั่นเป็นวิธีปกติในการรัน "super-class constructor" ใน Javascript และต้องทำแบบนั้นด้วยตนเอง
Jordão

46

คลาส JavaScript และการสืบทอด (ES6)

ตาม ES6 คุณสามารถใช้คลาส JavaScript และการสืบทอดเพื่อบรรลุสิ่งที่คุณต้องการได้

คลาส JavaScript ที่เปิดตัวใน ECMAScript 2015 ส่วนใหญ่เป็นการสังเคราะห์น้ำตาลมากกว่าการสืบทอดตามต้นแบบที่มีอยู่ของ 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.

27

คุณหมายถึงสิ่งนี้:

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

5
@HairOfTheDog ใช่คุณพลาดที่ได้รับคำตอบเมื่อประมาณห้าปีที่แล้วจาวาสคริปต์ในเวลานั้นไม่มีคลาสนามธรรมคำถามคือวิธีการจำลอง ( whattosayไม่ได้กำหนดไว้ในสัตว์ ) และคำตอบนี้ถามอย่างชัดเจน หากคำตอบที่เสนอคือสิ่งที่ผู้ถามกำลังมองหา ไม่ได้อ้างว่าให้วิธีแก้ปัญหาสำหรับคลาสนามธรรมในจาวาสคริปต์ ผู้ถามไม่รำคาญที่จะตอบกลับฉันหรือคนอื่นดังนั้นฉันไม่รู้ว่ามันใช้ได้ผลกับเขาไหม ฉันขอโทษถ้าคำตอบที่เสนอให้กับคนอื่นอายุห้าขวบไม่ได้ผลสำหรับคุณ
บาง

15

คุณอาจต้องการตรวจสอบคลาสฐานของ Dean Edwards: http://dean.edwards.name/weblog/2006/03/base/

หรือมีตัวอย่าง / บทความนี้โดย Douglas Crockford เกี่ยวกับการสืบทอดแบบคลาสสิกใน JavaScript: http://www.crockford.com/javascript/inheritance.html


13
เกี่ยวกับลิงค์ Crockford มันเป็นขยะมากมาย เขาได้เพิ่มหมายเหตุต่อท้ายบทความว่า: "ตอนนี้ฉันเห็นความพยายามครั้งแรกของฉันในการสนับสนุนรูปแบบคลาสสิกใน JavaScript ว่าเป็นความผิดพลาด"
Matt Ball

11

เป็นไปได้ไหมที่จะจำลองคลาสพื้นฐานแบบนามธรรมใน 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 = สัตว์ใหม่ ('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 () {... }; ดีกว่า?
fionbio

2
“ var c = function () {... }” จะสร้างการปิดทับอะไรก็ได้ใน subclass () หรือขอบเขตอื่น ๆ ที่มี อาจไม่สำคัญ แต่ฉันต้องการรักษาขอบเขตของผู้ปกครองที่อาจไม่ต้องการให้สะอาด ตัวสร้างฟังก์ชันข้อความบริสุทธิ์ () หลีกเลี่ยงการปิด
Bobince

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! 

คอนสตรัคเตอร์ของคลาสย่อยสามารถเรียกคอนสตรัคเตอร์ของซูเปอร์คลาสได้หรือไม่ (เช่นการเรียก super ในบางภาษา ... ถ้าเป็นเช่นนั้นมันจะเพิ่มข้อยกเว้นโดยไม่มีเงื่อนไข
nonopolarity

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

หากคุณไม่เข้าใจวิธีการทำงานอ่านเกี่ยวกับห่วงโซ่ต้นแบบ


โปรโตทำงาน AFAIK เฉพาะใน FF และ Chome (ทั้ง IE และ Opera ไม่รองรับฉันยังไม่ได้ทดสอบใน Safari) BTW คุณทำผิด: ควรแก้ไขคลาสพื้นฐาน (สัตว์) ทุกครั้งที่ต้องการสัตว์ประเภทใหม่
บางที่

ทั้ง Safari และ Chrome ใช้เครื่องมือจาวาสคริปต์เดียวกัน ฉันไม่แน่ใจจริงๆว่าเขาแค่อยากรู้ว่ามรดกทำงานอย่างไรดังนั้นฉันจึงพยายามทำตามตัวอย่างของเขาอย่างใกล้ชิดที่สุด
Georg Schölly

4
Safari และ Chrome ไม่ได้ใช้เครื่องมือ JavaScript เดียวกัน Safari ใช้JavaScriptCoreและ Chrome ใช้V8 สิ่งที่เบราว์เซอร์ทั้งสองร่วมกันเป็นเค้าโครงเครื่องยนต์, WebKit
CMS

@ GeorgSchöllyโปรดพิจารณาแก้ไขคำตอบของคุณเพื่อใช้โครงสร้าง Object.getPrototypeOf ใหม่
Benjamin Gruenbaum

@ Benjamin: ตาม Mozillaยังไม่มีsetPrototypeOfวิธีการใดที่ฉันต้องการรหัสของฉัน
Georg Schölly

5

คุณสามารถสร้างคลาสนามธรรมได้โดยใช้ต้นแบบวัตถุตัวอย่างง่ายๆมีดังนี้:

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

คุณสามารถเปลี่ยนวิธีการข้างต้นหรือไม่ก็ได้ขึ้นอยู่กับคุณเมื่อคุณนำไปใช้ สำหรับการสังเกตรายละเอียดของคุณอาจต้องการที่จะเยี่ยมชมที่นี่


5

คำถามค่อนข้างเก่า แต่ฉันได้สร้างวิธีการสร้าง "คลาส" นามธรรมและบล็อกการสร้างวัตถุประเภทนั้น

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

abstractที่คุณสามารถดูวัตถุที่ผ่านมาทำให้เรามีข้อผิดพลาดก็เป็นเพราะสัตว์ในต้นแบบที่มีคุณสมบัติ เพื่อให้แน่ใจว่ามันไม่ใช่ Animal ไม่ใช่สิ่งที่มีAnimal.prototypeอยู่ในห่วงโซ่ต้นแบบฉันทำ:

Object.getPrototypeOf(this).hasOwnProperty("abstract")

ดังนั้นฉันจึงตรวจสอบว่าวัตถุต้นแบบที่ใกล้เคียงที่สุดของฉันมีabstractคุณสมบัติเฉพาะวัตถุที่สร้างโดยตรงจากAnimalต้นแบบเท่านั้นที่จะมีเงื่อนไขนี้เป็นจริง ฟังก์ชันhasOwnPropertyตรวจสอบเฉพาะคุณสมบัติของวัตถุปัจจุบันไม่ใช่ต้นแบบของเขาดังนั้นสิ่งนี้ทำให้เราแน่ใจได้ 100% ว่าคุณสมบัติถูกประกาศที่นี่ไม่ได้อยู่ในห่วงโซ่ต้นแบบ

ทุกออบเจ็กต์ที่สืบเชื้อสายมาจาก Object จะสืบทอดเมธอดhasOwnProperty วิธีนี้สามารถใช้เพื่อพิจารณาว่าวัตถุมีคุณสมบัติที่ระบุเป็นคุณสมบัติโดยตรงของวัตถุนั้นหรือไม่ ซึ่งแตกต่างจากตัวดำเนินการในวิธีนี้ไม่ได้ตรวจสอบห่วงโซ่ต้นแบบของวัตถุ เพิ่มเติมเกี่ยวกับเรื่องนี้:

ในโจทย์ของฉันเราไม่จำเป็นต้องเปลี่ยนconstructorทุกครั้งหลังจากObject.createชอบคำตอบที่ดีที่สุดในปัจจุบันโดย @ Jordão

โซลูชันยังช่วยให้สามารถสร้างคลาสนามธรรมจำนวนมากตามลำดับชั้นเราจำเป็นต้องสร้างabstractคุณสมบัติในต้นแบบเท่านั้น


4

อีกสิ่งหนึ่งที่คุณอาจต้องการบังคับคือตรวจสอบให้แน่ใจว่าคลาสนามธรรมของคุณไม่ได้สร้างอินสแตนซ์ คุณสามารถทำได้โดยกำหนดฟังก์ชันที่ทำหน้าที่เป็น 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();

})()


2

เราสามารถใช้Factoryรูปแบบการออกแบบในกรณีนี้ Javascript ใช้prototypeเพื่อสืบทอดสมาชิกของพาเรนต์

กำหนดคอนสตรัคเตอร์คลาสพาเรนต์

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สำหรับตัวอย่างการเข้ารหัสแบบเต็ม


1
//Your Abstract class Animal
function Animal(type) {
    this.say = type.say;
}

function catClass() {
    this.say = function () {
        console.log("I am a cat!")
    }
}
function dogClass() {
    this.say = function () {
        console.log("I am a dog!")
    }
}
var cat = new Animal(new catClass());
var dog = new Animal(new dogClass());

cat.say(); //I am a cat!
dog.say(); //I am a dog!

นี่คือความหลากหลายใน JavaScript คุณสามารถตรวจสอบเพื่อใช้การแทนที่
Paul Orazulike

0

ฉันคิดว่าคำตอบทั้งหมดเหล่านั้นเป็นคำตอบเฉพาะสองข้อแรก (โดย บางคนและjordão ) ตอบคำถามได้อย่างชัดเจนด้วยแนวคิดพื้นฐาน JS แบบดั้งเดิม
ตอนนี้ตามที่คุณต้องการให้ตัวสร้างคลาสสัตว์ทำงานตามพารามิเตอร์ที่ส่งผ่านไปยังการก่อสร้างฉันคิดว่านี่คล้ายกับพฤติกรรมพื้นฐานของ 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

การเชื่อมโยงไปยังสิ่งนี้: programmers.stackexchange.com/questions/219543/…ตัวAnimalสร้างนี้สามารถมองได้ว่าเป็นการต่อต้านรูปแบบซึ่งซูเปอร์คลาสไม่ควรมีความรู้เกี่ยวกับคลาสย่อย (ละเมิดหลักการ Liskov และ Open / Close)
SirLenz0rlot

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();

ในมุมมองของฉันนี่เป็นวิธีที่ดีที่สุดในการได้ผลลัพธ์ที่ดีโดยใช้รหัสน้อยลง
Tamas Romeo

1
โปรดอธิบายว่าเหตุใดจึงมีประโยชน์ การแจกโค้ดแทบไม่มีประโยชน์เท่ากับการอธิบายว่าเหตุใดโค้ดจึงมีประโยชน์ ความแตกต่างระหว่างการส่งปลาให้ใครสักคนหรือสอนวิธีตกปลา
คนดีบุก

หลายคนไม่ได้ใช้ในต้นแบบหรือตัวสร้างเทคนิคการเขียนโปรแกรมจาวาสคริปต์ แม้ว่าจะมีประโยชน์ในหลาย ๆ สถานการณ์ก็ตาม. สำหรับสิ่งนั้นฉันคิดว่ารหัสนั้นมีประโยชน์ ไม่ใช่เพราะรหัสมันดีกว่าคนอื่น .. แต่เพราะมันเข้าใจง่ายกว่า
Tamas Romeo

0

หากคุณต้องการให้แน่ใจว่าคลาสพื้นฐานของคุณและสมาชิกของพวกเขาเป็นนามธรรมอย่างเคร่งครัดนี่คือคลาสพื้นฐานที่ทำเพื่อคุณ:

class AbstractBase{
    constructor(){}
    checkConstructor(c){
        if(this.constructor!=c) return;
        throw new Error(`Abstract class ${this.constructor.name} cannot be instantiated`);
    }
    throwAbstract(){
        throw new Error(`${this.constructor.name} must implement abstract member`);}    
}

class FooBase extends AbstractBase{
    constructor(){
        super();
        this.checkConstructor(FooBase)}
    doStuff(){this.throwAbstract();}
    doOtherStuff(){this.throwAbstract();}
}

class FooBar extends FooBase{
    constructor(){
        super();}
    doOtherStuff(){/*some code here*/;}
}

var fooBase = new FooBase(); //<- Error: Abstract class FooBase cannot be instantiated
var fooBar = new FooBar(); //<- OK
fooBar.doStuff(); //<- Error: FooBar must implement abstract member
fooBar.doOtherStuff(); //<- OK

โหมดที่เข้มงวดทำให้ไม่สามารถบันทึกผู้เรียกในเมธอด throwAbstract แต่ข้อผิดพลาดควรเกิดขึ้นในสภาพแวดล้อมการดีบักที่จะแสดงการติดตามสแต็ก

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.