클래스 #8
Replies: 4 comments
-
클래스자바스크립트는 프로토타입 기반 언어라서 ‘상속’ 개념이 존재하지 않습니다. 이는 클래스 기반의 다른 언어에 익숙한 많은 개발자들을 혼란스럽게 했고, 결국 ES6에는 클래스 문법이 추가됐습니다. 클래스와 인스턴스의 개념 이해배, 사과, 바나나 등은 직접 만질 수 있고 볼 수 있고 먹을 수 있는 구체적이고 실존하는 사물에 해당합니다. 반면, 음식이나 과일은 어떤 사물들의 공통 속성을 모아 정의한 것일 뿐 직접 만질 수도 볼 수도 없는 추상적인 개념입니다. 음식은 과일과의 관계에서 상위의(super) 개념이고 과일은 음식과의 관계에서 하위의(sub) 개념입니다. 음식, 과일은 모두 집단 즉, 클래스입니다. 여기서 앞의 이처럼 클래스는 하위로 갈수록 상위 클래스의 속성을 상속하면서 더 구체적인 요건이 추가 또는 변경됩니다. 물론 하위 클래스가 아무리 구체화되더라도 이들은 결국 추상적인 개념일 뿐입니다. 어떤 클래스의 속성을 지니는 실존하는 개체를 일컬어 인스턴스라고 합니다. 다시 말하자면 인스턴스는 그 클래스의 구체적인 예시라고 할 수 있습니다. 현실세계에서는 이미 존재하는 상태에서 이들을 구분짓기 위해 클래스를 도입했다면 프로그래밍 언어상에서는 접근 방식이 정반대입니다.
|
Beta Was this translation helpful? Give feedback.
-
7-2 자바스크립트의 클래스보통 클래스 입장에서 사용 대상에 따라 클래스 구성 요소를 정의하면 다음과 같다.
자바스크립트는 인스턴스에서도 직접 메서드를 정의할 수 있다. 따라서 '인스턴스 메서드'라는 명칭이 프로토타입에 정의한 메서드를 지칭하는 것인지 인스턴스에 정의한 메서드를 지칭하는 것인지 혼란을 준다. 프로토타입 메서드
프로토타입 메서드와 스태틱 메서드 예시// 생성자
var Rectangle = function(width, height) {
this.width = width;
this.height = height;
};
// 프로토타입 메서드
Rectangle.prototype.getArea = function() {
return this.width * this.height;
};
// 스태틱 메서드
Rectangle.isRectangle = function(instance) {
return (
instance instanceof Rectangle && instance.width > 0 && instance.height > 0
);
};
var rect1 = new Rectangle(3, 4);
console.log(rect1.getArea()); // 12 (O)
console.log(rect1.isRectangle(rect1)); // Error (X)
console.log(Rectangle.isRectangle(rect1)); // true 프로토타입 메서드 - getArea
스태틱 메서드 - isRectangle
자바스크립트에서의 클래스프로그래밍 언어에서의 클래스는 사용하기에 따라
|
Beta Was this translation helpful? Give feedback.
-
작성중7-3 클래스 상속7-3-1 기본 구현
앞에서 보았던 프로토타입 체인을 통해서 클래스 상속을 흉내내려고 한다. var Grade = function () {
var args = Array.prototype.slice.call(arguments);
for(var i = 0; i < args.length; i++) {
this[i] = args[i];
}
this.length = args.length;
}
Grade.prototype = [];
var g = new Grade(100, 80); 유사배열 객체인 Grade가 배열과 동일하게 Array의 내장 메서드를 사용하기 위해 작성한 예제이다.
Grade의 인스턴스 1. 프로퍼티가 삭제가 가능하다는 것기본적으로 JS는 객체가 생성되고 난 후에 프로퍼티의 삭제가 가능하다. 인스턴스의 프로퍼티가 삭제되는 것은 전혀 문제가 되지 않는다. 하지만 이 프로퍼티가 '상속 받은' 프로퍼티일 경우 문제가 발생할 수 있다. 이해하기 쉽게 '상속' 이라는 단어를 사용하였으나, prototype chain 상 prototype object와 동일한 프로퍼티를 말한다. Grade.prototype = [];
var g = new Grade(100, 80);
delete g.length;
g.push(70);
console.log(g); 인스턴스 2. 인스턴스의 prototype link가 인스턴스를 참조하고 있다는 것기본적으로 인스턴스의 프로퍼티를 조회하기 위해서 prototype chain을 거치게 된다. 인스턴의 Array의 인스턴스 였다면, 배열의 길이라는 의미가 사라질 수 없기 때문에
이렇게 '상속'을 흉내내기 위해 prototype chain을 사용하였고, 그 특성으로 인해 의도하지 않는 삽입이 이루어졌다. 이처럼 클래스의 값( 두 사용자 정의 클래스 사이의 상속을 구현해보자. var Rectangle = function (width, height) {
this.width = width;
this.height = height;
}
Rectangle.prototype.getArea = function () {
return this.width * this.height;
}
var Square = function (width) {
this.width = width;
}
Square.prototype.getArea = function () {
return this.width * this.width;
}
var Square = function (width) {
Rectangle.call(this, width, width);
}
Square.prototype = new Rectangle();
var sq = new Square(5); 하지만 여기에서도 문제가 발생할 수 있다.
두 가지 예제 모두 문제가 발생하는 이유는 클래스를 통해 상속하려는 prototype object에 프로퍼티가 존재하기 때문에 발생하고 있다. 이 프로퍼티는 prototype chain에 의해 인스턴스에 영향을 준다. 이를 피하는 방법을 설명하고자 한다. 7-3-2 클래스가 구체적인 데이터를 지니지 않게 하는 방법책에서 세가지 방법을 설명한다. 1. prototype object의 프로퍼티 삭제 및 freezedelete Square.prototype.width;
delete Square.prototype.height;
Object.freeze(Square.prototype);
2. 빈 생성자 함수를 하나 중간에 끼워 넣는다.var Bridge = function () {};
Bridge.prototype = Rectangle.prototype;
Square.prototype = new Bridge();
OBject.freeze(Square.prototype); 기존의 prototype link로 참조되는 인스턴스가 프로퍼티를 가질 때 생기는 문제였는데 프로퍼티를 가지지 않도록 하기 위해서 빈 객체를 prototype link로 참조하게끔 구현한다.
3. Object.create() 사용한다.위의 여러가지 문제를 해결하기 위해 ES에서 Square.prototype = Object.create(Rectangle.prototype);
OBject.freeze(Square.prototype); |
Beta Was this translation helpful? Give feedback.
-
7-3 클래스 상속7-3-3 constructor 복구하기
7-3-2의 세가지 방법 모두 기본적인 상속에는 성공했지만, SubClass 인스턴스의 constructor는 여전히 SuperClass를 가리키고 있다. var extendClass1 = function (SuperClass, SubClass, subMethods) {
// ...
SubClass.prototype.constructor = SubClass;
// ...
} 7-3-4 상위 클래스에의 접근 수단 제공하위 클래스 메서드에서 상위 클래스의 메서드 실행 결과를 바탕으로 추가적인 작업을 수행하고 싶을 때가 있다. 지금까지는 다른 객체지향 언어들의 클래스 문법 중 하나인 var extendClass1 = function (SuperClass, SubClass, SubMethods) {
SubClass.prototype = Object.create(SuperClass.prototype);
SubClass.prototype.constructor = SubClass;
SubClass.prototype.super = function (propName) { // 추가된 부분 시작
var self = this;
if (!propName) return function () {
SuperClass.apply(self, arguments);
}
var prop = SuperClass.prototype[propName];
if (typeof prop !== 'function') return prop;
return function () {
return prop.apply(self, arguments);
}
}; // 추가된 부분 끝
if (SubMethods) {
for (var method in SubMethods) {
SubClass.prototype[method] = SubMethods[method];
}
}
Object.freeze(SubClass.prototype);
return SubClass;
} 우리는 아래와 같이 사용할 수 있다. var Rectangle = function (width, height) {
this.width = width;
this.height = height;
};
Rectangle.prototype.getArea = function () {
return this.width * this.height;
};
var Square = extendClass1(
Rectangle,
function (width) {
this.super()(width, width);
}, {
getArea: function () {
console.log('size is :', this.super('getArea')());
}
}
);
var sq = new Square(10);
sq.getArea(); // size is : 100
console.log(sq.super('getArea')()); // 100 SuperClass의 프로토타입 메서드에 접근하고자 할 때는 this.super(propName)와 같이 사용 가능하다. |
Beta Was this translation helpful? Give feedback.
-
7-1 클래스와 인스턴스의 개념 이해
7-2 자바스크립트의 클래스
7-3 클래스 상속
7-3 클래스 상속
7-4 ES6의 클래스 및 클래스 상속
Beta Was this translation helpful? Give feedback.
All reactions