프로토타입을 이해하면서 우리는 이미 상속의 일면을 봤습니다.
클래스의 인스턴스는 클래스의 기능을 모두 상속합니다.
상속은 한 단계로 끝나지 않습니다.
객체의 프로토타입에서 메서드를 찾지 못하면 자바스크립트는 프로토타입의 프로토타입을 검색합니다.
프로토타입 체인 은 이런 식으로 만들어집니다.
자바스크립트는 조건에 맞는 프로토타입을 찾을 때까지 프로토타입 체인을 계속 거슬러 올라갑니다.
조건에 맞는 프로토타입을 찾지 못하면 에러를 일으킵니다.
클래스의 계층 구조를 만들 때 프로토타입 체인을 염두에 두면 효율적인 구조를 만들 수 있습니다.
즉, 프로토타입 체인에서 가장 적절한 위치에 메서드를 정의하는 겁니다.
자동차는 운송 수단의 읠종입니다.
예를 들어 자동차에는 deployAirbags 이란 메서드가 있을 수 있습니다.
이 메서드를 운송 수단 클래스에 정의할 수도 있겠지만, 에어백이 달린 보트는 본 적이 없겠죠?
반면 운송 수단은 대부분 승객을 태울 수 있으므로, addPassenger 메서드는 운송 수단 클래스에 적당합니다.
이런 시나리오를 자바스크립트로 만들어 봅시다.
class Vehicle {
constructor() {
this.passengers = [];
console.log("Vehicle created");
}
addPassenger(p) {
this.passengers.push(p);
}
}
class Car extends Vehicle {
constructor() {
super();
console.log("Car created");
}
deployAirbags() {
console.log("BWOOSH!");
}
}
처음 보는 키워드가 눈에 띕니다.
extends 키워드는 Car를 Vehicle의 서브클래스로 만듭니다.
super() 도 처음 보는 것입니다.
super() 는 슈퍼클래스의 생성자를 호출하는 특별한 함수입니다.
서브클래스에서는 이 함수를 반드시 호출해야 합니다.
호출하지 않으면 에러가 일어납니다.
예제를 봅시다.
class Vehicle {
constructor() {
this.passengers = [];
console.log("Vehicle created");
}
addPassenger(p) {
this.passengers.push(p);
}
}
class Car extends Vehicle {
constructor() {
super();
console.log("Car created");
}
deployAirbags() {
console.log("BWOOSH!");
}
}
const v = new Vehicle();
v.addPassenger("Frank");
v.addPassenger("Judy");
v.passengers; // ["Frank", "Judy"]
const c = new Car();
c.addPassenger("Alice");
c.addPassenger("Cameron");
c.passengers; // ["Alice", "Cameron"]
v.deployAirbags(); // error
c.deployAirbags(); // "BWOOSH!"
c에서는 deployAirbags를 호출할 수 있지만, v에서는 불가능합니다.
달리 말하면, 상속은 (당연히) 단방향입니다.
Car 클래스의 인스턴스는 Vehicle 클래스의 모든 메서드에 접근할 수 있지만, 반대는 불가능합니다.