피비의 격한 응원으로 시작해볼까.
BeeBeeBee 과제를 마치고 조금 아쉽다는 생각이 들어서 다들 (내가) 이 좋아하는 Friends의 등장인물로 class extends 상속 실습을 보기로 했다.
사실 등장 인물들은 캐릭터 클래스의 인스턴스 레벨이기는 한 것 같다. 모니카가 100명만 등장하는 게임을 만드는게 아니라면.. 응?? 좋은데?
⚠️ 스크롤 주의! 프렌즈를 스킵하고 본론으로 내려가려면 클릭!
** 생각해본 클래스 구조는 다음과 같다
├── Person
│ └── Character
│ ├── Ross
│ ├── Rachel
│ ├── Monica
│ ├── Phoebe
│ ├── Chandler
│ └── Joey
최상위 부모 클래스 Person
은 name
, gender
, job
멤버변수(이하 속성)을 가지고 있다.
class Person {
constructor(name, gender, job = 'unknown') {
this.name = name
this.gender = gender
this.job = job
}
}
job
은 ‘unknown’
으로 직업이 소개되지 않거나 Chandler처럼 아무도 모르는 경우, ‘unknown’
으로 출력한다.Person
을 상속받은 Character
는 Person
클래스의 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니까!)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)
Likability
를 정의하고 있지 않지만, Character로부터 Likability
를 상속받는다.Likability
는 Character
클래스에 초기값이 0
으로 할당되어 있다.// Ross name : Ross
// Ross said: "Hey, I'm Ross"
// Ross is a/an paleontologist.
// Ross likes dinosour!
// Ross Likability : 0
// Ross divorceCount : 2
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
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
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)
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
Chandler는 humor 속성이 있다. 🤣
class Chandler extends Character {
constructor(name, gender, favorite, humor, job) {
super(name, gender, favorite, job)
this.humor = humor
}
}
job
속성을 부여하지 않아, Chararcter
클래스의 job
속성의 ‘unknown'
초기값이 출력된다.// Chandler name : Chandler
// Chandler said: "Hey, I'm Chandler"
// Chandler is a/an unknown.
// Chandler likes Monica!
// Chandler humor : true
// Chandler Likability : 0
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()
를 반드시 호출해야 한다. (호출하지 않으면 나오는 아래처럼 레퍼런스 오류가 난다!)
[[ConstructorKind]]:"derived"
가 이름표처럼 붙는다.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.name
은 undefined
로 person.job
은 초기값인 ‘unknown’
으로 출력된다.
유어클래스 | 코드스테이츠
클래스 상속 | 모던 javascript 튜토리얼