extends와 super 실습(BeesBeesBees 회고)

김민아·2022년 7월 29일
0
post-thumbnail

피비의 격한 응원으로 시작해볼까.
BeeBeeBee 과제를 마치고 조금 아쉽다는 생각이 들어서 다들 (내가) 이 좋아하는 Friends의 등장인물로 class extends 상속 실습을 보기로 했다.
사실 등장 인물들은 캐릭터 클래스의 인스턴스 레벨이기는 한 것 같다. 모니카가 100명만 등장하는 게임을 만드는게 아니라면.. 응?? 좋은데?

⚠️ 스크롤 주의! 프렌즈를 스킵하고 본론으로 내려가려면 클릭!

Friends

Class structure

** 생각해본 클래스 구조는 다음과 같다

├── Person
│   └── Character
│       ├── Ross
│       ├── Rachel
│       ├── Monica
│       ├── Phoebe
│       ├── Chandler
│       └── Joey

class Person

최상위 부모 클래스 Personname, gender, job 멤버변수(이하 속성)을 가지고 있다.

class Person {
	constructor(name, gender, job = 'unknown') {
      this.name = name
      this.gender = gender
      this.job = job
	}
}
  • job‘unknown’으로 직업이 소개되지 않거나 Chandler처럼 아무도 모르는 경우, ‘unknown’으로 출력한다.

class Character

Person을 상속받은 CharacterPerson 클래스의 name, gender, job을 상속받고 favorite(좋아하는 것), likability(호감도)를 추가해 주었다.

만약 호감도가 5이상이라면 ‘People loves ${this.name}’을 출력해 준다.

class Character extends Person {
	constructor(name, gender, favorite, job, likability = 0) {
      super(name, gender, job)
      this.likability = likability
      this.favorite = favorite
	}
    sayHello() {
      console.log(`${this.name} said: "Hey, I'm ${this.name}"`)
    }
    talk() {
      console.log(`${this.name} likes ${this.favorite}!`)
    }
    loved() {
    if (this.likability >= 5) console.log(`People loves ${this.name}`)
  	}
  	occupation() {
      console.log(`${this.name} is a/an ${this.job}.`)
    }
}
  • 모든 캐릭터는 Character의 메서드를 상속받아 각자의 속성을 출력하도록 한다.
  • likability 속성은 초기값을 0으로 한다. (phoebe는 5부터 시작하도록, phoebe니까!)

class Ross

Ross는 이혼 횟수라는 속성을 가지고 있다. 😭

class Ross extends Character {
	constructor(name, gender, favorite, job, divorceCount) {
		super(name, gender, favorite, job)
		this.divorceCount = divorceCount
	}
}

let ross = new Ross('Ross', 'male', 'dinosour', 'paleontologist', 2)
  • Ross는 Likability를 정의하고 있지 않지만, Character로부터 Likability를 상속받는다.
  • LikabilityCharacter 클래스에 초기값이 0으로 할당되어 있다.
// Ross name : Ross
// Ross said: "Hey, I'm Ross"
// Ross is a/an paleontologist.
// Ross likes dinosour!
// Ross Likability : 0
// Ross divorceCount : 2

class Rachel

Rachel은 현재 만나고 있는 사람과 연애 횟수 속성을 가지고 있다. 🤗

class Rachel extends Character {
	constructor(name, gender, favorite, job, currRelationshipWith, relationshopCount) {
		super(name, gender, favorite, job)
		this.currRelationshipWith = currRelationshipWith
    	this.relationshopCount = relationshopCount
	}
}
let rachel = new Rachel('Rachel', 'female', 'creditcard', 'Waitress', 'Mark', 3)
// Rachel name : Rachel
// Rachel said: "Hey, I'm Rachel"
// Rachel is a/an Waitress.
// Rachel likes creditcard!
// Rachel Likability : 0
// Rachel Relationshop : 3

class Monica

Monica는 잔소리를 하거나 거슬리게 하면(beingAnnoying) 호감도가 떨어지는 메서드가 있다. 😤

class Monica extends Character {
	constructor(name, gender, favorite, job) {
		super(name, gender, favorite, job)
	}
    beingAnnoying() {
      	this.likability--
    }
}
let monica = new Monica('Monica', 'female', 'cleaning', 'cook')
  • monica.beingAnnoying() 메서드를 호출하면 Character 클래스로부터 받은 likability 속성이 1씩 떨어진다.
// Monica name : Monica
// Monica said: "Hey, I'm Monica"
// Monica is a/an cook.
// Monica likes cleaning!
// Monica Likability : 0

monica.beingAnnoying()
// Monica Likability : -1

class Phoebe

Phoebe는 사람을 도울 때마다 호감도가 상승(helpPeople)하는 메서드가 있다. 🥰

class Phoebe extends Character {
	constructor(name, gender, favorite, job, likability) {
		super(name, gender, favorite, job)
	    this.likability = likability
	}
    helpPeople() {
      	this.likability++
    }
}
let phoebe = new Phoebe('Phoebe', 'female', 'Frank', 'masseuse', 5)
  • Phoebe의 likability는 상속받았지만, 인스턴스 생성시 값이 오버라이딩 된다.
// Phoebe name : Phoebe
// Phoebe said: "Hey, I'm Phoebe"
// Phoebe is a/an masseuse.
// Phoebe likes Frank!
// Phoebe likability : 0

phoebe.helpPeople()
// Phoebe likability : 1

class Chandler

Chandler는 humor 속성이 있다. 🤣

class Chandler extends Character {
	constructor(name, gender, favorite, humor, job) {
		super(name, gender, favorite, job)
    	this.humor = humor
	}
}
  • Chandler는 job 속성을 부여하지 않아, Chararcter 클래스의 job 속성의 ‘unknown' 초기값이 출력된다.
  • 사실 챈들러는 직업이 있다. 통계 분석 및 데이터 재구성 전문가 (Statistical Analysis and Data Reconfiguration Specialist)'.. 그냥 unknown이라고 하자. 🤗
// Chandler name : Chandler
// Chandler said: "Hey, I'm Chandler"
// Chandler is a/an unknown.
// Chandler likes Monica!
// Chandler humor : true
// Chandler Likability : 0

class Joey

Joey는 pickupLine() 메서드가 있다.

class Joey extends Character {
	constructor(name, gender, favorite, job) {
		super(name, gender, favorite, job)
	}
    pickupLine() {
        console.log("How you doing~")
        this.likability--
    }
}
let joey = new Joey('Joey', 'male', 'food', 'actor')
  • joey.pickupLine()를 호출하면 Joey의 대사와 함께 호감도가 떨어진다.
// Joey name : Joey
// Joey said: "Hey, I'm Joey"
// Joey is a/an actor.
// Joey likes food!
// Joey job2 : actor

joey.pickupLine()
// How you doing~
// Joey Likability : -1

애정하는 프렌즈 주인공들로 롤플레잉 게임하는 기분이 들어 재밌었다. 오랜만에 추억이 새록새록-

class / instance를 실제 세계?에서 어떻게 구조적으로 적용할 수 있는지 많은 케이스를 배우면 좋겠다. 👀

BeesBeesBees 회고로 다시 돌아와서 이번 과제를 마치고 기억하고 싶은 내용은.

extends와 super()

상속 클래스는 (derived class)는 반드시 super()를 호출해야 한다.

먼저, extends로 상속받은 상속 클래스(이하 자식 클래스)에는 super()반드시 호출해야 한다. (호출하지 않으면 나오는 아래처럼 레퍼런스 오류가 난다!)

자식 클래스의 생성자가 호출될 때

  1. '자식 클래스의 생성자 함수(derived constructor)'와 그렇지 않은 생성자 함수를 구분한다.
  2. 자식 클래스의 생성자 함수엔 특수 내부 프로퍼티인 [[ConstructorKind]]:"derived"가 이름표처럼 붙는다.
  3. 일반 클래스가 new와 함께 실행되면 빈 객체가 만들어지고 this에 이 객체를 할당한다. 반면, 자식 클래스의 생성자 함수가 실행되면, 자식 클래스의 생성자 함수는 빈 객체를 만들고 this에 이 객체를 할당하는 일을 부모 클래스의 생성자가 처리해주길 기대한다.

이런 이유로 super()를 호출해 주지 않으면 this가 될 객체가 만들어지지 않아 에러가 발생한다.

그렇다면, super()은 왜 constructor()의 가장 위에 위치해야 할까?에 대한 질문도 이해가 된다.

this가 만들어지지 않으니까. this를 사용하기 전에 super()를 호출해야 하는 것.


부모 클래스에 직접 접근하면서 재사용 할 수 있는 방법 → 초기값 할당한다.

부모 클래스의 속성에 접근하고 또 자식 클래스에서도 재사용하고 싶다면 초기값을 설정해 준다.

const person = new Person()

console.log(person.name, person.job)
// undefined 'unknown'

위 friends 실습에서 최상위 Person 클래스의 person인스턴스을 접근하려고 하면, person.nameundefinedperson.job은 초기값인 ‘unknown’으로 출력된다.


출처

유어클래스 | 코드스테이츠
클래스 상속 | 모던 javascript 튜토리얼

0개의 댓글