무툴스 클래스 #
자바스크립트(1.x)는 클래스를 충분히 지원하지 않습니다. 무툴스는 자바스크립트의 객체 지향 프로그래밍을 어느 정도 지원합니다. 다음은 무툴스로 클래스를 만드는 가이드라인입니다.
클래스 정의 #
클래스를 정의할 때 멤버 변수는 initialize 메소드 안에서 정의하도록 합니다.
var Hello = new Class( {
initialize : function( hello ) {
this._hello = hello;
// this._world = null;
}
} );
초기화가 필요하지 않는 멤버 변수의 경우에도 명시적으로 표기하고 주석 처리하도록 합니다. 명시적으로 표기하면 클래스의 모든 멤버 변수들을 한눈에 확인할 수 있습니다. 주석으로 처리해서 늘어난 코드 양이 늘어나는 문제는 자바스크립트 최적화 툴로 해결할 수 있습니다.
접근 제어 #
자바스크립트(1.x)는 private, protected 등의 접근 제어를 지원하지 않습니다. 그러므로 멤버의 이름 규칙으로 접근 제어 기능을 대체하는 방법을 권장합니다. 즉, private 멤버의 이름의 첫 글자는 '_' 문자로 시작합니다.
이 방법 이외에 Closure를 이용해서 접근 제어 기능을 구현하는 방법도 있습니다. 그러나 코드가 복잡해지고 멤버 접근 방법이 이원화되는 단점이 있기 때문에 권장하지 않습니다.
스태틱(static) ...
클래스 상속 #
var Super = new Class( {
initialize : function( hello ) {
this._hello = hello;
}
} );
var Sub = Super.extend( {
initialize : function( hello, world ) {
this.parent( hello );
this._world = world;
}
} );
상위 클래스의 함수에 접근 #
무툴스는 오버라이드를 단순히 상위 클래스의 함수를 덮어쓰지 않고, 상위 클래스의 함수를 접근할 수 있도록 구현해놨습니다. 이때, 상위 클래스의 함수는 항상 this.parent로 접근하게 됩니다.
var Super = new Class( {
initialize : function( hello ) {
this._hello = hello;
},
say : function() {
alert( this._hello );
}
} );
var Sub = Super.extend( {
initialize : function( hello, world ) {
this.parent( hello );
this._world = world;
},
say : function() {
this.parent();
alert( this._world );
}
} );
위의 예에서 Sub 클래스의 인스턴스 sub를 생성한 후, sub.say()를 호출해보면, Super.say()도 호출되는 것을 확인하실 수 있습니다. 이는 무툴스의 클래스를 확장하는 소스를 보시면 방법을 확인하실 수 있습니다. 복잡한 조건문들을 의사코드로 대체하고 코드를 보면 다음과 같습니다.
extend : function( properties ) {
var pr0t0typ3 = new this('noinit'); // Super의 간이 인스턴스 생성
var parentize = function( previous, current ) {
return function() {
// previous와 current는 클로저로 만들어져,
// 각각 Super의 함수와 Sub의 함수를 가리키게 됩니다.
this.parent = previous;
return current.apply( this, arguments );
};
}
for ( var name in properties ) {
var previous = pr0t0typ3[ name ];
var current = properties[ name ];
if ( 상위 클래스와 하위 클래스에 동일한 이름의 property가 있으면 ) {
if ( 둘 다 함수이면 )
current = parentize( previous, current );
}
pr0t0typ3[ name ] = current;
}
return new Class( pr0t0typ3 );
}
위의 소스코드에서 properties를 복사하는 과정을 보시면, Super와 Sub에 같은 이름의 property가 있고, 둘다 함수인 경우, 해당 property는 다음과 같은 코드로 대체됨을 알 수 있습니다.
function() {
this.parent = previous;
return current.apply( this, arguments );
}
때문에, Super의 함수를 오버라이드 하게 되면, Sub의 해당 함수는 항상 this.parent = previous가 실행된 후에 실행되게 됩니다. 때문에 오버라이드된 함수에서 this.parent()를 호출하게 되면, 항상 Super의 동명 함수를 호출할 수 있게 됩니다.
구현 방법의 제한으로, Super의 함수는 오버라이드 된 함수 외에서는 접근할 수 없다는 한계가 있습니다.
무툴스 1.1에서의 변경점 #
무툴스 1.1에서는 클래스 상속 구현에 추가된 기능이 있습니다. 객체의 처리와 부모함수 접근 방법인데요, 하나씩 설명해보겠습니다.
우선 클래스의 객체의 경우 (static member?) 기존의 무조건 새로운 객체가 덮는 형태가 아닌, 재귀적으로 객체를 합치는 구조를 가지게 되었습니다. 객체 속성의 객체는 합치고, 기본 자료형(String, Number 등)의 경우에는 새로운 클래스의 것으로 대체되는 등의 규칙으로 객체를 합쳐, 상위 클래스의 객체를 어느정도 유지하면서 상속을 할 수 있도록 하였습니다.
var Super = new Class( {
hello = {
hello : "hello"
}
} );
var Sub = Super.extend( {
hello = {
world : "world"
}
} );
위의 코드에서, 기존의 무툴스 클래스라면, Sub의 인스턴스를 생성하면, hello 객체 밑에 world속성밖에 남아있지 않지만, 무툴스 1.1의 클래스에서는 hello 객체 밑에 hello와 world 모두가 존재하게 됩니다.
부모 함수 접근의 경우에는, 기존에는 현재 클래스의 오버라이드 한 함수 내에서만 부모의 동명 함수에 접근할 수 있었지만, 새로운 무툴스 1.1의 클래스에서는 외부에서도 동명의 부모 함수에 접근할 수 있게 되었습니다. 사용 방법은 다음과 같습니다.
var Super = new Class( {
initialize : function() {
this._super = "Super";
}
say : function() {
alert( this._super );
}
} );
var Sub = Super.extend( {
initialize : function() {
this._sub = "Sub";
}
say : function() {
alert( this._sub );
}
} );
var sub = new Sub();
sub.say(); // "Sub"
sub.say.parent.apply( sub ); // "Super"
이렇게 함수객체.parent 를 통해서 동명의 부모 함수에 접근할 수 있는데요, 이때 주의할 점은 apply를 통해서 인스턴스를 바인딩 시켜줘야 한다는 점입니다. 이는 다음 버전에서는 좀 더 쉽게 사용할 수 있게 되지 않을까 기대해봅니다.







