[코어 자바스크립트] Class Inheritance

소이뎁·2023년 7월 10일
0
post-thumbnail

🌈 인프런의 코어 자바스크립트(정재남) 수강 후, 이해한 내용을 정리한 글입니다.

📍 아래는 학습을 위해 ES6의 extends를 사용하지 않고 구현한 class inheritance입니다. extends 사용 코드는 맨 아래에 있습니다.

Class Inheritance는 한 클래스가 다른 클래스로부터 속성과 메서드를 상속받는 것을 의미한다.

예시로 사용할 2개의 class가 있다. 두 class에는 getName(), getAge()라는 공통된 메서드가 있다.

// Person class
function Person(name, age) {
	this.name = name || '이름없음';
  	this.age = age || '나이모름';
}

Person.prototype.getName = function() {
	return this.name;
}
Person.prototype.getAge = function() {
	return this.age;
}

// Employee class
function Employee(name, age, position) {
	this.name = name || '이름없음';
  	this.age = age || '나이모름';
  	this.position = position || '직책모름';
}

Employee.prototype.getName = function() {
	return this.name;
}
Employee.prototype.getAge = function() {
	return this.age;
}
Employee.prototype.getPosition = function() {
	return this.position;
}

Person -> Employee 상속하려면

두 class를 연결해 주는 비어있는 class인 Bridge가 필요하다.

어떻게 연결하냐면

Bridge class를 Person class와 겹친다. Person의 instance와 Employee.prototype을 직접 연결하지 않는 이유는 name: '이름없음', age: '나이없음'과 같은 프로퍼티는 제외하고 getName(), getAge()와 같은 메서드만 상속하고 싶기 때문이다.

코드로 표현하면

아래와 같다.

  • 1️⃣ 상위 class의 prototype에 공통된 메서드만 정의한다.
  • 2️⃣ Bridge class를 생성한다.
  • 3️⃣ Bridge.prototype과 상위 class의 prototype을 연결한다.
  • 4️⃣ 하위 class의 prototype과 Bridge의 instance를 연결한다.
  • 5️⃣ 하위 class의 prototype.constructor에 하위 class constructor를 할당한다.
  • 6️⃣ 하위 class의 prototype에 하위 class에만 존재하는 메서드를 정의한다.(4️⃣ 이전에 정의하면 어차피 prototype이 new Bridge로 재할당되므로 소용 없음)
// 1️⃣ 상위 class의 prototype에 공통된 메서드만 정의한다.
// Person class
function Person(name, age) {
	this.name = name || '이름없음';
  	this.age = age || '나이모름';
}

Person.prototype.getName = function() {
	return this.name;
}
Person.prototype.getAge = function() {
	return this.age;
}

// Employee class
function Employee(name, age, position) {
	this.name = name || '이름없음';
  	this.age = age || '나이모름';
  	this.position = position || '직책모름';
}
// 2️⃣ Bridge class를 생성한다.
function Bridge() {}
// 3️⃣ Bridge.prototype과 상위 class의 prototype을 연결한다.
Bridge.prototype = Person.prototype;
// 4️⃣ 하위 class의 prototype과 Bridge의 instance를 연결한다.
Employee.prototype = new Bridge();
// 5️⃣ 하위 class의 prototype.constructor에 하위 class constructor를 할당한다.
Employee.prototype.constructor = Employee;
// 6️⃣ 하위 class의 prototype에 하위 class에만 존재하는 메서드를 정의한다.
Employee.prototype.getPosition = function() {
	return this.position;
}

var roy = new Employee();

instance roy 생성 후 콘솔을 확인하면 아래와 같이 [[Prototype]]에 Person이 들어가 상속된 것을 볼 수 있다.

2️⃣ ~ 5️⃣ 함수화하기

Bridge class는 자주 등장하는 패턴이고, 매개체 역할만 할 뿐 실제 코드에 영향을 주지 않는다. 때문에 2️⃣ ~ 5️⃣을 함수화하여 1번만 작성하고 필요할 때마다 불러서 사용할 수 있다.

// 1️⃣ 상위 class의 prototype에 공통된 메서드만 정의한다.
// Person class
function Person(name, age) {
	this.name = name || '이름없음'; // ⭐️
  	this.age = age || '나이모름'; // ⭐️
}

Person.prototype.getName = function() {
	return this.name;
}
Person.prototype.getAge = function() {
	return this.age;
}

// Employee class
function Employee(name, age, position) {
	this.name = name || '이름없음'; // ⭐️
  	this.age = age || '나이모름'; // ⭐️
  	this.position = position || '직책모름';
}
// 2️⃣ ~ 5️⃣
var extendClass = (function() {
	function Bridge(){}
  	return function(Parent, Child) {
    	Bridge.prototype = Parent.prototype;
      	Child.prototype = new Bridge();
      	Child.prototype.constructor = Child;
    }
})();
// 함수 사용
extendClass(Person, Employee);
// 6️⃣ 하위 class의 prototype에 하위 class에만 존재하는 메서드를 정의한다.
Employee.prototype.getPosition = function() {
	return this.position;
}

var roy = new Employee();

부모 class의 프로퍼티를 자식 class에 상속하기(name, age)

위의 코드에서 ⭐️ 부분이 중복된다. this를 통해 name과 age를 Employee class에 상속하여 코드 중복을 피할 수 있다. ✅ 부분이 변경, 추가되었다.

// 1️⃣ 상위 class의 prototype에 공통된 메서드만 정의한다.
// Person class
function Person(name, age) {
	this.name = name || '이름없음';
  	this.age = age || '나이모름';
}

Person.prototype.getName = function() {
	return this.name;
}
Person.prototype.getAge = function() {
	return this.age;
}

// Employee class
function Employee(name, age, position) {
  	// 📍 메서드 호출 시 this 호출 => this === 메서드를 호출한 주체 === this === roy
	this.superClass(name, age); // ✅ Prototype Chain을 타고 Enployee.prototype에 있는 superClass 호출
  	this.position = position || '직책모름';
}
// 2️⃣ ~ 5️⃣
var extendClass = (function() {
	function Bridge(){}
  	return function(Parent, Child) {
    	Bridge.prototype = Parent.prototype;
      	Child.prototype = new Bridge();
      	Child.prototype.constructor = Child;
      	Child.prototype.superClass = Parent; // ✅
    }
})();
// 함수 사용
extendClass(Person, Employee);
// 6️⃣ 하위 class의 prototype에 하위 class에만 존재하는 메서드를 정의한다.
Employee.prototype.getPosition = function() {
	return this.position;
}

var roy = new Employee(); // 📍 생성자 함수 호출 시 this 호출 => this === instance === roy

사실 이렇게 안 해도 돼 ES6에는 extends가 있거든

아래처럼 작성하면 위와 동일하게 작동하는 코드를 작성할 수 있다.

class Person() {
  	constructor(name, age) {
    	this.name = name || '이름없음';
  		this.age = age || '나이모름';
    }
	getName() {
    	return this.name;
    }
  	getAge() {
    	return this.age;
    }
}

class Employee extends Person {
	constructor (name, age, position) {
    	super(name, age);
      	this.position = position || '직책모름';
    }
  	getPosition() {
    	return this.position;
    }
}

3줄 요약

  • Bridge class를 만들어 Class Inheritance를 구현할 수 있다.
  • 함수화, this를 통해 코드 중복을 줄일 수 있다.
  • ES6에는 Class Inheritance를 간단하게 구현할 수 있는 extends가 있으니, 그것을 사용하자.

0개의 댓글