2006년 10월 13일 금요일

상속(Inheritance)

언어에서 상속이 가지는 의미는 크게 몇 가지로 나눌 수 있습니다.
  1. 부모의 속성과 메소드를 자식들이 가진다.
  2. 부모의 메소드를 재정의할 수 있어야 한다. (Overriding)
  3. 부모를 호출 할 수 있어야 한다. (Java에서의 super키워드)
문제는, 'JavaScript에서 상속을 명시적으로 제공하지 않는다'에서 발생합니다. 이를 해결하기 위해서 여러명이 고민하였고 그 결과 몇가지 방법이 나왔습니다.

Object masquerading
(masquerading는 '가장 무도회', '가장', '겉치레'라는 의미를 가지고 있습니다. )


장점:  상속 기능 제공 시 사용자가 원하는 argument를 생성자에 넣을 수 있습니다.
단점:  상속을 emulation하는 것이기 때문에 instanceof 사용 시 false를 리턴합니다.

Prototype Chaining
prototype을 이용한 상속으로 prototype에 생성자를 대입하는 방법을 사용합니다.
장점: prototype을 이용하여 상속하므로 instaneof를 사용하는 경우 true값이 리턴됩니다.
단점: Class를 만들 때 argument를 지정할 수 없습니다.

# 위의 코드를 실험해보다 var objB = new ClassB("blue", "Nicholas");라는 코드를 호출 해 보았습니다. 이 때, 위의 코드에서 에러는 발생하지 않습니다. - firefox에서- 위의 코드처럼 new ClassB(); 를 호출한 효과와 동일한 효과를 얻습니다.

Hybrid Method
Hybrid Method는 Object Masqerading과 Prototype Chaining을 섞은 방법입니다.

Prototype extend
prototype.js에서는 상속을 Object의 extend 메소드를 사용하여 처리를 하고 있습니다.

Object Masqerading이나 Prototype Chaining하고는 다르게 파라미터와 관련된 문제를 Class.create()를 사용하여 생성자 호출 부분을 변경하였고, 상속에 필요한 기능은 extend 메소드에서 property의 내용을 복사합니다.

※ 실제로 상속하는 것이 아니라, prototype을 copy함으로서 상속을 시뮬레이션하게 됩니다.
※※ 부모의 prototype을 child의 prototype으로 복사하게 됩니다.
※※※  제가 알고있던 기존의 상속방법에서 instanceof가 동작하기는 하였으나 하나의 부모를 여러 자식들이 상속받을 때, 부모의 메소드를 덮어써버리는 문제가 발생하였습니다.

prototype.js의 파일들을 뒤져서 상속코드들을 다시 살펴보니, prototype의 method들만 상속받고 Class자체를 상속받지는 않더군요. prototype.js의 파일들을 살펴보면 다음과 같은 방식으로 정의되어 있습니다.

공유할 메소드들을 정의를 합니다. (즉, 부모 클래스에 해당하는 내용들이겠죠.)

var Enumerable = {
    each: function((iterator) {},
    eachSlice: function((number, iterator) {},
    all: function((iterator) {},
  ...
}

공유할 메소드들을 받을 클래스를 생성합니다.

ObjectRange = Class.create();

생성한 클래스에 공유할 메소드들을 상속받습니다. (복사합니다.)

Object.extend(ObjectRange.prototype, Enumerable);

새로운 메소드들을 추가합니다. (순서는 중요합니다. 순서가 바뀔경우 (이름이 같다면) 공유할 메소드들이 새로운 메소드들을 덮어쓸 수 있겠죠.)

Object.extend(ObjectRange.prototype, {
    initialize: function((start, end, exclusive) {},
    _each: function(iterator) {},
    ...
}

prototype.js를 사용해서, 상속의 조건 중 하나인 instanceof를 만족하는 상속의 방법은 없는 것 같습니다...

출처 :
P.S:
질문: object를 array로 출력하는 경우 prototype자체가 나올까요?
정답: 안나옵니다.

※ JavaScript의 Object에 관해서 설명해 놓은 Objectifying JavaScript에 대한 글을 봤습니다.
글의 내용은 JavaScript에서 어떻게 Object를 생성할 것인가에 대한 글이였구요. Object를 생성하기 위해서는
  • Object 자체를 생성하는 방법 var obj = new Object(); obj.property = "sample"; 과 같이 생성하는 방법과
  • Function을 사용하는 방법 function Object() {...} var obj = new Object();
두가지를 사용할 수 있다. prototype을 사용하여 동일한 프로퍼티와 메소드를 레퍼런스를 사용하여 접근할 수 있다. 생성자, 싱글턴, 팩토리 패턴을 만들 수 있다... 로 요약(?)할 수 있겠네요.

※※ Objectifying JavaScript와 관련하여 보다가 ECAM-262 표준(4.2.1 Objects)도 살펴보았습니다. 모든 생성자는 explicit하게 prototype chain이라 불리는 prototype에 레퍼런스를 가지고 있습니다. 그리고, 동일한 생성자를 통해서 생성된 객체들의 경우 implicit하게 prototype chain을 레퍼런스하고 있습니다.
사용자 삽입 이미지

CF - 생성자, Cfp - prototype chain, cf1, cf2, .. cf5 - 객체

※※※ Object를 생성하기 위해서 new 연산자를 사용하여 생성자를 호출하는 경우에, prototype property를 저장하기 위한 __proto__ 라는 property를 생성합니다 . 이를 이용해서 prototype chain에 접근할 수 있게 됩니다. 다음은 Mozilla에 올라와 있는 관련 글입니다.
JavaScript Object Layout(via Ajaxian)에 나와있는 그림처럼 __proto__ 를 따라가다보면 Object.__proto__, Object의 prototype chain에 도달하게 됩니다.
사용자 삽입 이미지
이러한 속성을 이용해서 instanceof 메소드를 만들 수도 있습니다. prototype을 비교하기 때문에 상속관계를 체크할 수 있습니다.
function instanceOf(object, constructor) {
while (object != null) {
if (object == constructor.prototype)
return true;
object = object.__proto__;
}
return false;
}

댓글 6개:

  1. 상속에 대한 내용을 정리하고 있습니다.

    답글삭제
  2. @감마 - 2007/07/11 10:09
    죄송합니다만.. 광고성 댓글로 보이는데.. 이번은 삭제하지 않겠습니다만, 안달아주셨으면 합니다.

    답글삭제
  3. @감마 - 2007/08/08 22:13
    광고가 아니라면 제가 오해를 한 것 같네요. 죄송하구요. 그러나 자바스크립트와 같이 상속을 기본적으로 지원하지 않는 언어에서 어떻게 상속을 구현할 것인가에 대한 글의 댓글에 '상속에 대한 내용을 정리하고 있습니다.'라는 댓글만 쓰신다면 오해하기 쉽지 않을까 싶네요. ^^;;

    좋은 하루 되시고 제 댓글로 기분 상하셨다면 푸시기 바랍니다.

    답글삭제
  4. 프로그램 언어 관점에서 상속(Inheritance)은 하나의 이론적인 개념(Concept)으로 볼 수 있습니다. 상속을 지원하는 언어도 있고 그렇지 않은 언어도 있습니다. 하지만 지원하지 않는 언어에서 상속을 구현해 보면서 어떤 이점을 얻으려는 시도는 그 자체로 재미있는 것이죠. 이러한 관점의 논문들도 있구요. 그냥 언어에서 제공하는 특징만을 사용하는 분은 아닌 것 같아서요. 그래서, 간단히 '상속에 대한 내용을 정리하고 있습니다'라고만 적어 보았습니다. 혹 이런 내용을 현재 정리되어 있는 글에 첨가하실까 해서.. ^(^

    답글삭제
  5. 정리되고 있는 글을 보시고도 광고성 댓글이라 생각하신다면 삭제해 주세요. 인터넷에 전문적인 글을 정리하고 있는 분들은 그나마 지식을 공유하고 발전시켜 갈 생각을 가지신 분들이라 생각하고 옷장수님의 사이트에 댓글을 남긴 것입니다. Google광고 때문이었다면 오해가 없길 바랍니다.

    답글삭제
  6. @감마 - 2007/08/08 22:12
    네 알겠습니다. ^^;;

    답글삭제