Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

prototype.js에서 클래스 상속(inheritance)하기

아래의 포스팅에서 prototype.js에서 제공하는 클래스 부분에 대한 설명을 했는데 OOP에 중요한 특징인 상속에 대해서 좀 보자. 이번 프로젝트에서 클래스 상속은 우리가 가진 설계의 핵심부분이었기 때문에 많이 중요했는데 처음엔 잘 안되서 좀 힘들었었다.

일단 자바스크립트에서는 상속이라는 개념을 제공하지 않는다. prototype이라는 기능을 제공하고 있기는 하지만 상속이라기 보다는 확장에 훨씬 가까운 느낌이다. 그래서 완젼(?)한 OOP를 위해서 프로토타입 프레임워크는 상속을 위한 extend라는 메서드를 제공하고 있다.

Object.extend(destination, source);

가 기본적인 extend의 사용법이다. source부분에 있는 객체의 모든 프로퍼티를 destination 객체로 복사한다. 어찌보면 완전한 상속이라고 하기엔 좀 다른 부분이 있다.(아직 난 OOP의 개념조차 좀 부족하기 때문에...)

이렇게 상속을 하면 destinatio측의 클래스 객체를 이용해서 source쪽에 있는 변수나 메서드를 사용할 수 있다. 한클래스 안에 모두 넣어도 되지만 클래스를 구분함으로써 더욱 명확한 구조를 가질 수 있다.


// Object.extend 사용 예제
var Dog = Class.create();
Dog.prototype =  {
    initialize: function(mapId) {
        this.name  = "gae";
        this.age   = 2;
    },

    myName: function() {
        alert(this.name);
    }
}

var Cow = Class.create();
Cow.prototype =  {
    initialize: function(mapId) {
        this.sex  = "male";
        this.weight   = 100;
    },

    myWeight: function() {
        alert(this.weight);
    }
}

var animal = new Dog();
var bull = new Cow();

Object.extend(animal, bull);

alert(animal.name);
alert(animal.sex);
animal.myName();
animal.myWeight();

이렇게 상속을 받을 경우 인스턴스 animal을 사용해서 Dog과 cow의 변수 및 메서드를 모두 사용할 수 있다. 자신의 것은 당연한거고 Cow에 있던 것을 상속받았기 때문에 사용이 가능하다. 여기에 나는 하나의 인스턴스를 이용해서 다양한 기능을 구현할 것이지만 클래스를 구조를 이용하기 위해서 중심이 되는 클래스 하나만 객체로 만들어서 사용하기를 원했다. 즉 이건 식의 사용도 가능하다.


// Object.extend 사용예제
var Dog = Class.create();
Dog.prototype =  {
    initialize: function(mapId) {
        this.name  = "gae";
        this.age   = 2;

        var bull = new Cow();   
        Object.extend(this, bull);  //상속
    },

    myName: function() {
        alert(this.name);
    }
}

var Cow = Class.create();
Cow.prototype =  {
    initialize: function(mapId) {
        this.sex  = "male";
        this.weight   = 100;
    },

    myWeight: function() {
        alert(this.weight);
    }
}

var animal = new Dog();

alert(animal.name);
alert(animal.sex);
animal.myName();
animal.myWeight();

Dog클래스 내부에서 Cow의 인스턴스를 만들어서 바로 상속을 받음으로써 외부에서는 Dog의 인스턴스만 만들어서 모든 기능을 사용할 수 있다.(난 약간은 다른 형태로 했는데 되겠지? ㅡ..ㅡ)


여기서 메서드든 변수든 같은 이름이 있을 경우는 어떻게 될까?

extend가 프로퍼티를 복사한다고 했으므로 당연히 덮어쓰는 효과가 된다. 즉 Overriding 효과가 난다. 이걸 이용하면 의도적으로 특정 메서드를 오버라이드 할 수 있다. 오버라이딩할 클래스를 나중에 상속받아오면 되니까... 당연히 다중상속도 가능하지만 위의 말한대로 이름이 겹칠경우 오버라이딩 되기 때문에 의도하지 않는 문제가 생기지 않도록 네이밍에 주의를 기울여야 한다.

추가로 이번에 작업을 준비하면서 여러가지로 테스트를 좀 했었는데 public 변수나 함수는 모두 this. 를 이용해서 접근할 수 있는데 이것은 상속받아온 곳에서도 동일하게 사용가능하다. 예를 들어 바로 위의 예제에서 Cow클래스에서 this.name을 접근해서 사용해도 가능하다는 것이다. (물론 Cow 인스턴스를 따로 만들어서 사용한다면 오류가 생기겠지...) extend된 상황에서는 this가 Dog클래스를 가르키고 있기 때문에.....
2008/02/29 00:59 2008/02/29 00:59