프로토타입 클래스 #

프로토타입을 이용해서 클래스를 상속할 때 약간의 문제가 있습니다.

클래스 정의 #

프로토타입을 이용해서 클래스를 정의하는 방법은 아래와 같습니다.
var Hello = Class.create();
Hello.prototype = {
    initialize : function( hello ) {
        this.hello = hello;
    }
};

클래스 상속 #

프토로타입에서 클래스를 상속하려면 Object.extend을 이용하며, 첫번째 인자에 상위 클래스의 인스턴스를 만들어서 넘겨줍니다.
var Super = Class.create();
Super.prototype = ( {
    initialize : function( hello ) {
        this.hello = hello;
    }
} );

var Sub = Class.create();
Sub.prototype = Object.extend( new Super(), {
        initialize : function( hello, world ) {
            this.hello = hello;
            this.world = world;
        }
    }
);
그런데 이 방법은 initialize를 항상 재정의 해줘야 하는 불편이 있으며 상위 클래스의 생성자(initialize)를 호출할 수 있는 방법이 없기 때문에 코드의 중복이 발생합니다. 그리고 상위 클래스의 인스턴스에 정의 되었던 멤버 변수가 하위 클래스의 prototype으로 복사되기 때문에 garbage가 발생합니다.

Class.extend #

프로토타입 클래스 상속시 생기는 코드 중복과 garbage를 막기 위해서 Class.extend라는 함수를 정의하였습니다. (이 방법보다는 무툴스 프레임워크를 이용하는 것을 권장합니다. 만약 현재 프로젝트에 프로토타입이 적용되어 무툴스로 전환이 어려운 경우는 아래 방법을 참고하십시오. 단, 아래는 개략적인 방향만 설정한 예제 소스입니다)
Class.extend = function( base, methods ) {
    var destination = {};
    var basePrototype = base.prototype;
    if ( null == basePrototype ) {
        throw Error( "Super is not class" );
    }

    for ( var name in parentPrototype ) {
        destination[ name ] = parentPrototype[ name ];
    }
    
    for ( var name in methods ) {
        destination[ property ] = methods[ property ];
    }
    
    destination._initialize = function( base ) {
        var args = $A( arguments );
        args.shift();
        base.prototype.initialize.apply( this, args );
    };
    
    return destination;
};
일단, 첫번째 인자가 클래스가 아닌 경우 예외를 발생합니다. 멤버 변수가 프로토타입에 복사되는 것을 막기 위해서인데, 이 경우 상위 클래스에 직접 정의된 속성은 복사되지 않습니다(약간의 코드 추가로 해결 가능합니다).

Object.extend와 달리 새로운 인스턴스를 만들어서 상위 클래스의 prototype과 새로 정의된 메소드를 복사한 후 리턴합니다. 그리고 _initialize라는 메소드가 추가되는데, 이 메소드는 상위 클래스의 생성자를 호출합니다.

Class.extend를 이용해서 클래스를 상속하는 방법은 아래와 같습니다.
var Super = Class.create();
Super.prototype = ( {
    initialize : function( hello ) {
        this.hello = hello;
    }
} );

var Sub = Class.create();
Sub.prototype = Class.extend( Super, {
        initialize : function( hello, world ) {
            this._initialize( hello );
            this.world = world;
        }
    }
);
하위 클래스의 생성자에서 _initialize를 항상 호출해야 합니다. 이를 통해 상위 클래스의 initialize가 연쇄적으로 호출되며, 상위 클래스에 정의된 멤버 변수를 중복적으로 정의하지 않아도 됩니다.

Mootools #

세상은 넓고 고수들은 많습니다. 이 문제를 훨씬 더 우아한 방법으로 해결한 무툴스라는 프레임워크가 있습니다.
Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2009-09-04 15:45:01
Processing time 0.2138 sec