본문 바로가기

TIL ( CODESTATES)

pseudoclassical vs.ES 6 class 인스턴스화와 상속 (sprint)

코드스테이츠 immersive 4주차 과정 'inheritance patterns'에 대해 학습한 내용을 궁금했던 점들과 함께 정리해 보았다.

 

 

스프린트 내용 

클래스 structur와 정해진 스펙에 따라 각 클래스를 구현한다.

 

 


ES 6 Class Instantiation & Inheritance 

 

class Grub {
  constructor(age, color, food){ // 질문 1.
    this.age = 0;
    this.color = 'pink';
    this.food = 'jelly';
  }
  eat() {
    return 'Mmmmmmmmm jelly';
  }
}

module.exports = Grub;

 

질문 1. constructor에 인자를 전달하지 않아도 되나?

 

전달 인자로 들어가는 값이 만들어질 instance의 속성에 상관없이 고정된 값을 주게 된다면 괄호 안에 속성을 명시할 필요는 없지만

그 경우가 아니면 명시해 주어야 한다.

class Rectangle {
  constructor(height, weight){
    this.height = height;
    this.weight = weight;
  }
}

위 생성자 함수로부터 새로운 instance를 생성할 때 new Rectangle(10,10) 처럼 인자를 전달해 주어야 this의 height, weight이 지정된다.

 


 

  • extends 키워드를 통해 superclass의 constructor를 상속할 수 있다.(sub classing)
  • subclass에 constructor가 있으면 this를 사용하기 전에 먼저 super()를 호출해야 한다.
  • 왜냐하면 this는 super()를 호출하지 않으면 초기화되지 않기 때문
  • super 키워드는 superclass의 함수들을 호출하기 위해 사용한다.
  • subclass는 constructor를 가지지 않을 수도 있지만, 가지는 경우엔 반드시 super()를 호출해야 한다.
const Grub = require('./Grub');

class Bee extends Grub{
  constructor(age, color, food, job){
    super(food)	// 질문 2. super 괄호 안에 인자를 생략해도 되나? 
    super.eat()		// 상속받은 메소드를 그대로 사용하려면 명시하지 않아도 되나?
    this.age = 5;
    this.color = 'yellow';
    this.job = 'Keep on growing'
  }
}

module.exports = Bee;

 

질문 2. 상속받은 속성이나 메서드를 그대로 사용할 경우 super 괄호 안에 인자를 명시하지 않거나 메서드를 명시하지 않아도 되나?

가능하다.

Grub의 속성과 메서드를 그대로 상속받기 때문에 굳이 명시할 필요가 없다.

 

질문 3. constructor 안에는 새로 명시할 내용만 인자로 전달하면 안 되나?

새로 정의할 부분만 인자로 명시하면 된다.

 

그래서 수정하면 다음과 같다.

class Bee extends Grub{

  constructor(age, color,job){
    super();
    this.age = 5;
    this.color = 'yellow';
    this.job = 'Keep on growing';
  }
}

 주의! 만약 constructor에는 food가 없는데 super 괄호 안에 food 가 있으면 food 가 undeinfed 이므로 referenceError가 나온다.

 


const Bee = require('./Bee');

class HoneyMakerBee extends Bee{
  constructor(age, job, honeyPot){
    super();
    this.age = 10;
    this.job = 'make honey';
    this.honeyPot = 0;
  }
  makeHoney() {
    this.honeyPot++;
  }
  giveHoney() {
    this.honeyPot--;
  }
}

module.exports = HoneyMakerBee;

 

const Bee = require('./Bee');

class ForagerBee extends Bee{

  constructor(age,job, canFly, treasureChest){
    super();
    this.age = 10;
    this.job = 'find pollen'
    this.canFly = true;
    this.treasureChest = [];
  }
  forage(treasure) {
    this.treasureChest.push(treasure)
  }
}

module.exports = ForagerBee;

 

 


pseudoclassical instantiation & Inheritance

: ES6 Class 개념이 나오기 전 

 

var Grub = function (age, color, food) {
    this.age = 0;
    this.color = 'pink';
    this.food = 'jelly';
};
Grub.prototype.eat = function() {
    return 'Mmmmmmmmm jelly'
}


module.exports = Grub;

 

var Grub = require('./Grub');

var Bee = function (age, color, food, job) { 
    Grub.call(this, age, color, food); // 질문 1.
    this.age = 5;
    this.color = 'yellow';
    this.job = 'Keep on growing';
};
Bee.prototype = Object.create(Grub.prototype); // 중요 1.
Bee.prototype.constructor = Bee;		// 중요 2.

module.exports = Bee;

 

질문 1. call 안에 모든 인자를 명시해 주어야 하나?

??

 

중요 1. Object.create()의 인자로 들어가 있는 Grub.prototype의 객체 및 속성을 갖는 새로운 객체를 생성하여 Bee.prototype에 할당했다.

중요 2. 여전히 Bee의 prototype은 Bee 임을 명시했다. 

 

 

var Grub = require('./Grub');

var Bee = function (age, color, food, job){
    Grub.call(this);
    this.age = 5;
    this.color = 'yellow';
    this.job = 'keep on growing';
};
Bee.prototype = Object.create(Grub.prototype);
Bee.prototype.constructor = Bee;

module.exports = Bee;

 

위 코드처럼 call 의 인자로 this만 전달해도 잘 작동했다.

부모로부터 상속하여 변경 없이 그대로 쓰는 food도,

부모로부터 상속 받은 게 의미가 없이 재정의한 age나 color도 call의 인자로 넣지 않아도 작동이 되어서 헷갈린다.

 

심지어 function 괄호 안에 인자들을 전부 명시하지 않아도 작동이 되던데 왜 명시해야하는지 궁금하다.

 

 


var Bee = require('./Bee');

var HoneyMakerBee = function (age, job, color,food, honeyPot) {
    Bee.call(this, color, food); //나는 재정의하는 속성 말고 상속만 받는 속성은 명시하기로 했다.
    this.age = 10;
    this.job = 'make honey';
    this.honeyPot = 0;
};

HoneyMakerBee.prototype = Object.create(Bee.prototype);
HoneyMakerBee.prototype.constructor = HoneyMakerBee;

HoneyMakerBee.prototype.makeHoney = function(){ // 중요 3.
    this.honeyPot++;
}
HoneyMakerBee.prototype.giveHoney = function() {
    this.honeyPot--;
}
module.exports = HoneyMakerBee;

 

중요 3. subclass에서 새로운 매서드를 생성할 때에는 반드시 객체를 먼저 생성하고 만들어야 한다.

 

 


var Bee = require('./Bee');

var ForagerBee = function (age, job, color, food, canFly, treasureChest) {
    Bee.call(this, color, food);
    this.age = 10;
    this.job = 'find pollen';
    this.canFly = true;
    this.treasureChest = [];
};
ForagerBee.prototype = Object.create(Bee.prototype);
ForagerBee.prototype.constructor = ForagerBee;

ForagerBee.prototype.forage = function(treasure){ 
    this.treasureChest.push(treasure);
}

module.exports = ForagerBee;