상속 in Class
- 클래스 (Class)
- Object Oriented (OO)
- 작동위임 (Behavior Delegation)
- Ojects Linking to Other Objects (OLOO)
클래스 Object Oriented (OO)
- prototype을 이용한 클래스 상속
function Widget(width, height) {
this.width = width || 50;
this.height = height || 50;
this.$elem = null;
}
Widget.prototype.render = function($where) {
if (this.$elem) {
this.$elem.css({
width: this.width + 'px',
height: this.height + 'px'
}).appendTo($where);
}
};
function Button(width, height, label) {
// super
Widget.call(this, width, height);
this.label = label || 'Default';
this.$elem = $('<button>').text(this.label);
}
Button.prototype = Object.create(Widget.prototype);
// overriding (shadowing)
Button.prototype.render = function($where) {
// super
Widget.prototype.render.call(this, $where);
this.$elem.click(this.onClick.bind(this));
}
BUtton.prototype.onClick = function(evt) {
console.log(this.label + ' 버튼이 클릭됨!');
}
$(document).ready(function() {
var $body = $(document.body);
var btn1 = new Button(125, 30, 'Hello');
var btn2 = new Button(150, 40, 'World');
btn1.render($body);
btn2.render($body);
});
- ES6 class를 이용한 클래스 상속
class Widget {
constructor(width, height) {
this.width = width || 50;
this.height = height || 50;
this.$elem = null;
}
// Widget.prototype.render와 같음
render($where) {
if (this.$elem) {
this.$elem.css({
width: this.width + 'px',
height: this.height + 'px'
}).appendTo($where);
}
}
}
// 파생 클래스 (derived class)
class Button extends Widget {
constructor(width, height, label) {
super(width, height);
this.label = label || 'Default';
this.$elem = $('<button>').text(this.label);
}
// Button.prototype.render와 같음
// overriding (shadowing)
render($where) {
super($where); // TODO : 다시 확인
this.$elem.click(this.onClick.bind(this));
}
// Button.prototype.onClick와 같음
onClick(evt) {
console.log(this.label + ' 버튼이 클릭됨!');
}
}
$(document).ready(
// 위와 동일
);
- super()
- 파생 클래스 생성자에서만 super()를 사용할 수 있다
- 만약 파생 클래스가 아닌 클래스(extends를 사용하지 않은 클래스)나 함수에서 사용하려면 에러가 발생한다
- 생성자 내의 this에 접근하기 전에 super()를 호출해야만 한다
- super()는 this를 초기화하는 역할을 하기 때문에, super()를 호출하기 전에 this에 접근하려면 에러가 발생한다.
- super()를 호출하지 않는 유일한 방법은 클래스 생성자에서 객체를 반환하는 것이다.
// 파생 클래스 (derived class) class Button extends Widget { // 생성자(constructor) 없음 } // 위와 같음 class Button extends Widget { // 파생 클래스에서 생성자(constructor)를 명시하려면 반드시 super()를 사용해야만 하고, 그렇지 않으면 에러가 발생한다 // 클래스 선언에서 생성자를 사용하지 않는 경우, 클래스의 새 인스턴스를 만들 때 전달된 모든 인자와 함께 super()가 자동으로 호출된다 constructor(...args) { super(...args); } }
작동위임 Ojects Linking to Other Objects (OLOO)
var Widget = {
init: function(width, height) {
this.width = width || 50;
this.height = height || 50;
this.$elem = null;
},
insert: function($where) {
if (this.$elem) {
this.$elem.css({
width: this.width + 'px',
height: this.height + 'px'
}).appendTo($where);
}
}
};
var Button = Object.create(Widget);
Button.setup = function(width, heigth, label) {
// delegation
this.init(width, height);
this.label = label || 'Default';
this.$elem = $('<button>').text(this.label);
};
Button.build = function($where) {
// delegation
this.insert($where);
this.$elem.click(this.onClick.bind(this));
};
Button.onClick = function(evt) {
console.log(this.label + ' 버튼이 클릭됨!');
};
$(document).ready(function() {
var $body = $(document.body);
var btn1 = Object.create(Button);
btn1.setup(125, 30, 'Hello');
var btn2 = Object.create(Button);
btn2.setup(150, 40, 'World');
btn1.build($body);
btn2.build($body);
});
- OLOO 관점에서는 Widget이 부모도, Button이 자식도 아니다.
- Widget은 보통 객체로 갖가지 유형의 위젯이 위임하여 사용할 수 있는 유틸리티 창고 역할을 맡는다.
- Button은 단독으로 존재하는 객체일 뿐이다(Widget과 위임 링크를 맺은)
- 클래스 스타일에서처럼 render()와 같이 같은 이름의 메서드를 공유할 필요가 없다. (overriding 필요없어짐)
- 생성자, .prototype, new 등이 불필요하게 되어 훨씬 더 간단하게 디자인할 수 있다.