책 모던 JavaScript를 읽으면서 프로토타입, 클래스를 배운 후 JavaScript에서는 다른 언어에서 사용할 수 있는 다중 상속을 사용할 수 있는 지 직접 정리해본 글입니다.
다중상속(Multiple inheritance)이란 객체 지향 프로그래밍의 특징 중 하나이며, 어떤 클래스가 하나 이상의 상위 클래스로부터 여러 가지 행동이나 특징을 상속받을 수 있는 것을 말한다.
출처: 위키백과 - 다중 상속
위 정의와 같이 다중 상속은 클래스가 여러개의 부모로 부터 상속을 받을 수 있는 지와 관련한 것입니다. 이번에 자바스크립트에 대해 깊게 배우면서 이러한 생각을 해보았습니다.
JS도 프로토타입 기반 객체지향 언어인데 (클래스도 지원하는) 다중 상속을 할 수 있지 않을 까? 였습니다.
이 궁금증을 한번 해결해 보기 위해 다른 언어들과 비교하여 한번 다중 상속 코드를 작성 해보았습니다.
파이썬
class Person:
def greeting(self):
print("안녕하세요.")
class University:
def manage_credit(self):
print("학점 관리")
class Undergraduate(Person, University):
def study(self):
print("공부하기")
jm = Undergraduate()
jm.greeting() # 안녕하세요
jm.manage_credit() # 학점 관리
jm.study() # 공부하기
Cpp
#include <iostream>
using namespace std;
class Person {
public:
void greeting() {
cout << "안녕하세요" << endl;
}
};
class University {
public:
void manage_credit() {
cout << "학점 관리" << endl;
}
};
class Undergraduate : public Person, public University {
public:
void study() {
cout << "공부 하기" << endl;
}
};
int main() {
Undergraduate jm;
jm.greeting(); // 안녕하세요
jm.manage_credit(); // 학점 관리
jm.study(); // 공부하기
return 0;
}
JavaScript
class Person {
greeting() { return "안녕하세요"; }
}
class University {
manage_credit() { return "학점 관리"; }
}
class Undergraduate extends Person, University {
study() { return "공부하기"; }
}
코드의 결과는...
위 사진에서 보는 것과 같이 콤마로 두 개의 클래스를 상속받으려고 하면 SyntaxError가 발생해 다중상속이 되지 않는 모습을 볼 수 있었습니다.
그렇다면 Class는 다중 상속이 안된다고 치고, 프로토타입으로는 다중상속이 가능한 지 한번 실험을 해보았습니다.
function Person() { }
Person.prototype.greeting = function () { return "안녕하세요"; }
function University() { }
University.prototype.manage_credit = function() { return "학점 관리"; }
function Undergraduate() { }
Undergraduate.prototype.study = function() { return "공부하기"; }
const me = new Undergraduate();
me.study(); // 공부하기
me.manage_credit(); // Uncaught TypeError me.manage_credit is not a function
me.greeting(); // Uncaught TypeError me.greeting is not a function
// 배열로 두 프로토타입을 동시에 프로토타입의 프로토타입 체인으로 연결한 경우
Undergraduate.prototype.__proto__ = [University.prototype, Person.prototype];
me.greeting(); // Uncaught TypeError: me.greeting is not a function
me[0].manage_credit(); // 학점 관리
me[1].greeting(); // 안녕하세요
// 프로토타입 체인으로 하나하나 연결한 경우
Undergraduate.prototype.__proto__ = University.prototype;
University.prototype.__proto__ = Person.prototype;
me.manage_credit(); // 학점관리
me.greeting(); // 안녕하세요
다음과 같이 배열로 한번에 프로토타입을 연결 시켜주게되면 기존 프로토타입처럼 참조할 수가 없기 때문에 프로토타입 체인끼리 연결 시켜주면 다중 상속을 한 것처럼 보이게 할 수는 있었습니다.
결론부터 말씀드리면 그렇다고합니다.
자바스크립트는 단일 상속만을 허용하는 언어로, 객체엔 단 하나의 [[Prototype]]
만 존재하며, 클래스는 클래스 하나만 상속받을 수 있습니다.
다중상속이 없는 경우, 다중상속을 사용하고 싶은경우 JS는 믹스인이라는 개념이 사용하면 도움이 될 것입니다.
위키피디아에선 믹스인을 다른 클래스를 상속받을 필요없이 이들 클래스에 구현되어 있는 메서드를 담고 있는 클래스라고 정의합니다.
출처: https://ko.javascript.info/mixins
자바스크립트에서 믹스인을 구현할 수 있는 가장 쉬운 방법은 유용한 메서드 여러 개가 담긴 객체를 하나 만드는 것입니다. 이렇게 하면 다수의 메서드를 원하는 클래스의 프로토타입에 쉽게 병합할 수 있습니다.
아래 예시의 믹스인 sayHiMixin
은 User
에게 '언어 능력’을 부여해줍니다.
// 믹스인
let sayHiMixin = {
sayHi() {
alert(`Hello ${this.name}`);
},
sayBye() {
alert(`Bye ${this.name}`);
}
};
// 사용법:
class User {
constructor(name) {
this.name = name;
}
}
// 메서드 복사
Object.assign(User.prototype, sayHiMixin);
// 이제 User가 인사를 할 수 있습니다.
new User("Dude").sayHi(); // Hello Dude!
믹스인을 활용하면 User
가 아래 예시처럼 다른 클래스를 상속받는 동시에, 믹스인에 구현된 추가 메서드도 사용할 수 있습니다.
class User extends Person {
// ...
}
Object.assign(User.prototype, sayHiMixin);