이번 소개할 내용은 객체지향 언어의 중요 개념인 상속입니다.
이 상속도 ES2015 클래스 명령의 등장과 함께 변경된 부분이 있기에 두가지를 설명하도록 하겠습니다.
1. 상속
상속을 간단하게 말하자면 클래스나 기초가 될 객체의 기능(프로퍼티나 메소드)을 이어 받아 새로운 클래스나 객체를 정의하는 것 입니다.
상속에서 상속을 해주는 대상이 되는 클래스를 부모클래스, 슈퍼클래스, 베이스 클래스 등으로 부르고 상속을 받는 클래스는 자식클래스, 서브 클래스, 파생 클래스라고 부릅니다.
(이 글에서는 부모-자식 클래스라는 표현을 사용할 예정입니다.)
이에 대한 설명은 아래 예시로 한 방에 정리가 가능합니다.
스마트폰과 공중전화기는 둘 다 전화기라는 공통을 갖고있습니다. 만약 스마트폰과 공중전화기 두 객체를 만든다면 똑같이 전화걸기, 전화받기라는 공통적인 행동(메소드)을 갖고 있는데, 이 똑같은 행동(메소드)을 두 객체에 담으면 같은 코드가 두 번 사용되어 코드가 길어지고, 작성 효율이 떨어지는 것을 보입니다. 그래서 전화걸기와 받기라는 메소드를 담은 전화기 클래스를 정의하고 스마트폰과 공중전화기에 상속을 시키면 두 객체에서 전화걸기와 받기라는 동일메소드를 따로 선언하지 않아도 되게 됩니다.
이때 전화기 클래스는 부모 클래스가 되고, 스마트폰과 공중 전화기 클래스는 자식 클래스가 되는 것 입니다.
또한 자식 클래스는 부모 클래스에서 상속받은 메소드나 프로퍼티를 오버라이드(재정의하다.)할 수 있습니다. 오버라이드라 함은 상속 받은 기능을 자식클래스에서 입맛에 맞게 변경하는 것을 의미합니다. 단, 오버라이딩 할 시 프로퍼티 혹은 메소드의 이름은 유지하고 기능만 변경해야합니다. (이것을 바꾸면 그냥 새로운 프로퍼티/메소드를 정의한 것)
2. 프로토타입 체인
상속이야기 하다가 갑자기 어려운 영어가 등장?
...은 아니고 자바스크립트에선 이러한 상속 개념을 프로토타입 체인이라고 합니다. 이전의 클래스 포스트에서 자바스크립트는 클래스가 존재하는 것이 아니라 프로토타입에 기반한 객체라고 했기에 클래스의 상속보단 프로토타입 체인이 바른 표현이 맞기 때문입니다.
이하의 내용은 ES2015 이전의 프로토타입 체인 이용법입니다.
let Phone = function () {}; //부모 클래스 Phone과 생성자
Phone.prototype.getCall = function () {
return '전화 받기';
}
let SmartPhone = function () {
Phone.call(this); //Phone클래스 생성자를 자식 클래스에서 호출
}
SmartPhone.prototype = new Phone(); //프로토타입 체인 실시
let smartPhone = new SmartPhone(); //전화기 클래스를 상속받은 스마트폰 객체 생성
console.log(smartPhone.getCall());
우선 Phone 클래스를 생성하고 getCall이라는 메소드를 정의했습니다. 그리고 스마트폰 클래스를 정의하고 프로토타입 체인을 실시합니다. 그리고 스마트폰 객체에서 getCall()메소드를 호출합니다.
우리가 아는대로라면 스마트폰객체에는 getCall()메소드가 없으므로 오류가 나야하는데, Phone객체를 프로토타입 체인 했으므로 Phone 클래스의 geteCall() 메소드에 접근할 수 있게 되었습니다.
위에서 오버라이드와 메소드 추가가 가능하다고 했으니 그것도 한 번 해보도록 하겠습니다.
let Phone = function () {
};
Phone.prototype.getCall = function () {
return '전화 받기';
}
let SmartPhone = function () {
Phone.call(this);
}
SmartPhone.prototype = new Phone();
SmartPhone.prototype.getCall = function () { //getCall() 메소드 오버라이딩
return '스마트폰 전화 받기';
};
SmartPhone.prototype.playMusic = function () { //메소드 추가
return '음악 재생';
};
let smartPhone = new SmartPhone();
console.log(smartPhone.getCall());
console.log(smartPhone.playMusic());
3. 상속 extends 키워드 (ES2015 적용)
ES2015 이전 상속은 위의 프로토타입 체인에서 보이듯이 낮설고 복잡한 면을 보입니다. 그러나 class 명령이 들어오면서 extends 키워드를 같이 들고 오게 되면서 상속도 간편해졌습니다. 사용법도 간단하게 자식클래스의 클래스명 다음에 extends 키워드를 넣고 부모 클래스의 이름을 적으면 됩니다.
class Phone {
constructor() {
}
getCall() {
return '전화 받기';
}
}
class SmartPhone extends Phone{
}
let smartPhone = new SmartPhone();
console.log(smartPhone.getCall());
위의 프로토타입 체인과 비교해도 어마무시하게 간편해졌습니다.
마찬가지로 오버라이딩과 메소드 추가도 해보겠습니다.
class Phone {
constructor() {
}
getCall() {
return '전화 받기';
}
}
class SmartPhone extends Phone{
constructor() {
super(); //일단 무시!
}
getCall() {
return '스마트폰 전화 받기 by class';
}
playMusic(){
return '음악 재생';
}
}
let smartPhone = new SmartPhone();
console.log(smartPhone.getCall());
console.log(smartPhone.playMusic());
4. super
위에서 생성자 부분을 보면 super();라는 명령어가 띡! 등장합니다. super는 부모 클래스의 생성자나 메소드를 호출하는데 이용하는 키워드입니다. 위의 재정의 예시에서 등장했듯이 super 키워드는 보통 오버라이드 상황에서 등장합니다.
기본적인 사용법은 다음과 같습니다.
//생성자 super
super(인수, ...);
//메소드 super
super.method(인수, ...);
class Member {
constructor(name) {
this.name = name;
}
getInfo() {
return '이름: ' + this.name;
}
}
class Student extends Member {
constructor(name, id) {
super(name);
this.id = id;
}
getInfo() {
return super.getInfo() + ', 학번:' + this.id;
}
}
let student = new Student('밤', '123456');
console.log(student.getInfo());
Student 클래스에서 생성자의 name은 부모 클래스 Member의 생성자를 호출하여 이용했고 id 프로퍼티는 추가했습니다.
그리고 getInfo()메소드에서 이름 출력하는 부분은 부모클래스에서 호출하고 학번 출력만 따로 오버라이드 해서 사용하는 모습을 보여줍니다.
'Programming > Javascript' 카테고리의 다른 글
[Javascript] 노드 취득 (0) | 2021.03.24 |
---|---|
[Javascript] 문서 객체 모델 DOM (0) | 2021.03.23 |
[Javascript] class 명령을 이용한 클래스 정의 (0) | 2021.03.19 |
[Javascript] this (0) | 2021.03.18 |
[Javascript] 객체와 클래스 (0) | 2021.03.18 |
댓글