LHJ

I'm a FE developer.

9.2.5 상속

10 May 2020 » js_lj

프로토타입을 이해하면서 우리는 이미 상속의 일면을 봤습니다.
클래스의 인스턴스는 클래스의 기능을 모두 상속합니다.
상속은 한 단계로 끝나지 않습니다.
객체의 프로토타입에서 메서드를 찾지 못하면 자바스크립트는 프로토타입의 프로토타입을 검색합니다.
프로토타입 체인 은 이런 식으로 만들어집니다.
자바스크립트는 조건에 맞는 프로토타입을 찾을 때까지 프로토타입 체인을 계속 거슬러 올라갑니다.
조건에 맞는 프로토타입을 찾지 못하면 에러를 일으킵니다.

클래스의 계층 구조를 만들 때 프로토타입 체인을 염두에 두면 효율적인 구조를 만들 수 있습니다.
즉, 프로토타입 체인에서 가장 적절한 위치에 메서드를 정의하는 겁니다.
자동차는 운송 수단의 읠종입니다.
예를 들어 자동차에는 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 클래스의 모든 메서드에 접근할 수 있지만, 반대는 불가능합니다.