source

자바스크립트에서 추상 베이스 클래스를 만들려면 어떻게 해야 합니까?

manysource 2023. 9. 27. 18:00

자바스크립트에서 추상 베이스 클래스를 만들려면 어떻게 해야 합니까?

자바스크립트에서 추상 베이스 클래스 시뮬레이션이 가능합니까?가장 우아한 방법은 무엇입니까?

저는 다음과 같은 일을 하고 싶습니다.

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

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

출력해야 합니다.

meow
bark

JavaScript 클래스 및 상속(ES6)

ES6에 따르면 자바스크립트 클래스와 상속을 사용하여 필요한 작업을 수행할 수 있습니다.

ECMAScript 2015에서 도입된 자바스크립트 클래스는 주로 자바스크립트의 기존 프로토타입 기반 상속에 대한 구문적 당(syntical sugar)입니다.

참조 : 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.

추상 클래스를 만드는 간단한 방법은 다음과 같습니다.

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

여기를 만지작거립니다(콘솔 출력 보기).

이런 뜻입니까?

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

Dean Edwards의 Base Class: http://dean.edwards.name/weblog/2006/03/base/ 을 확인해 볼 수 있습니다.

또는, 자바스크립트의 고전적 상속에 대한 더글러스 크록포드의 글인 http://www.crockford.com/javascript/inheritance.html 이 있습니다.

자바스크립트에서 추상 베이스 클래스 시뮬레이션이 가능합니까?

물론입니다.자바스크립트에서 클래스/인스턴스 시스템을 구현하는 방법은 약 천 가지가 있습니다.여기 하나 있습니다.

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

질문은 꽤 오래되었지만 추상적인 "클래스"를 생성하고 해당 유형의 개체를 생성하는 블록 생성 방법을 가능한 해결책을 만들었습니다.

//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.prototype프로토타입 체인에서 다음과 같은 작업을 수행합니다.

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

을 가지고 합니다.abstract,성에서 직접 tAnimal프로토타입은 이 조건이 참입니다.능.hasOwnProperty프로토타입이 아닌 현재 객체의 속성만 확인하므로 프로토타입 체인이 아닌 여기서 속성이 선언됨을 100% 보장합니다.

Object의 하위 개체는 모두 hasOwnProperty 메서드를 상속합니다.이 메서드는 개체가 해당 개체의 직접 속성으로 지정된 속성을 가지고 있는지 여부를 확인하는 데 사용할 수 있습니다. in operator와 달리 이 메서드는 개체의 프로토타입 체인을 확인하지 않습니다.자세한 내용:

제 는 를 .constructor 이후에 매번Object.create@Jordango의 현재 베스트 답변에 있는 것처럼.

솔루션을 할 수 , 하면 됩니다. 우리는 단지 생성하기만 하면 됩니다.abstract원형의 재산

또한 추상 클래스가 인스턴스화되지 않도록 해야 합니다.FLAG 클래스 생성자로 설정된 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();

})()
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에서는 작동합니다.

어떻게 작동하는지 이해가 안 되면 프로토타입 체인에 대해 읽어 보십시오.

객체 프로토타입을 사용하여 추상 클래스를 만들 수 있으며 간단한 예는 다음과 같습니다.

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

위의 방법을 변경할 수도 있고 변경하지 않을 수도 있으며, 그것을 실행할 때는 당신에게 달려 있습니다.자세한 관찰을 위해 이곳을 방문하는 것이 좋습니다.

자바스크립트는 상속이 가능하며, 아래 URL을 확인해보세요.

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

앤드루

사용할 수 있습니다.Factory이 경우 디자인 패턴.자바스크립트 사용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~

전체 예제 코딩을 위한 코드펜 링크입니다.

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

제 생각에는 모든 것들이 (일부조르당에 의해) 기존의 프로토타입 베이스 자바스크립트 개념으로 질문에 명확하게 답한다고 생각합니다.

이제 당신이 동물급 건설자가 구조에 전달된 매개변수에 따라 행동하기를 원하기 때문에, 나는 이것이 기본적인 행동과 매우 비슷하다고 생각합니다.Creational Patterns예를 들어 공장 패턴입니다.

여기서 저는 그런 식으로 작동하기 위해 약간의 접근을 했습니다.

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

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

기본 클래스와 기본 클래스의 구성원이 완전히 추상적인지 확인하려면 다음과 같이 작업을 수행하는 기본 클래스가 있습니다.

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

strict 모드를 사용하면 throwAbstract 메서드에서 호출자를 기록할 수 없지만 스택 추적을 표시하는 디버그 환경에서 오류가 발생해야 합니다.

"use strict";



function Abstract (...arg){
    
    // create abstract constructor
    if(  this.constructor.name === 'Object' || this.constructor === Abstract ) throw { ErrorType : "can't call abstract class with new !" , }
 

    // ceate abstract method
    Object.defineProperty( this , 'config' , {
        value : function(){
            console.log('config parent')
        }
    });


    // or other 
    return this ;
};
 

class Home extends Abstract{
    name = '';
    constructor(...arg){
        super(...arg) ; 
    }

    config(){
        // this method not working
        console.log('config child')
    }
}

let y = new Home( "home" , 'dasd');
y.config();

ES6 Classes 및 new.target 사용

class Animal {
  constructor() {
    if(new.target===Animal)
    throw new Error('Cannot be instantiated')
  }
  //Non-abstract method
  makeSound()
  {
     console.log(this.sound);
  }
}

class Cat extends Animal {
  constructor(sound) {
    super();
    this.sound = sound;
  }
}

class Dog extends Animal {
  constructor(sound) {
    super();
    this.sound = sound;
  }
}

let cat1 = new Cat('Meow')
cat1.makeSound();
let dog1 = new Dog('Bark')
dog1.makeSound();
let genericAnimal = new Animal(); //Throws Error

//ES6 - Abstract class with Abstract and Non-Abstract methods
class Animal {
  constructor() {
    if(new.target===Animal)
    throw new Error('Abstract Class cannot be instantiated')
  }
  //abstract method
    makeSound()
  {
     throw new Error('Abstract Method cannot be called')
  }
  //non-abstract method
  displayType()
  {
     console.log(this.name," instanceof Animal",this instanceof Animal);
  }
}

class Cat extends Animal {
  constructor(name,sound) {
    super();
    this.name = name;
    this.sound = sound;
  }
  //abstract method defined in child class implementation
  makeSound()
  {
     console.log("Cat ",this.name, " is making ", this.sound);
  }
}

class Dog extends Animal {
  constructor(name,sound) {
    super();
    this.name = name;
    this.sound = sound;
  }
}
//Dog.prototype.constructor = Dog;

let cat1 = new Cat('Bella','Meow')
cat1.makeSound();
cat1.displayType();
let dog1 = new Dog('Jimmy','Bark')
dog1.displayType();
dog1.makeSound(); //throws error
//let genericAnimal = new Animal(); //throws error

언급URL : https://stackoverflow.com/questions/597769/how-do-i-create-an-abstract-base-class-in-javascript