티스토리 뷰

hacking/web

dojo by example(7) - object system

Ho Eyo He Hum! iolo 2008.08.20 23:06
여름 휴가도 있고... 밥먹고 사는 일도 있고 해서... 한참 쉬었으니 다시 시작해보자.

dojo의 객체 시스템의 핵심은 dojo.declare다:
  • dojo.declare(className, superClass, { members... }) : 주어진 이름을 가진 클래스를 정의한다. 클래스 이름은 문자열로, 수퍼클래스는 클래스 객체로 지정해야 한다. 수퍼클래스가 없으면 null 또는 [ ] (빈 배열)을 지정하면 된다. 하나 이상의 수퍼클래스(정확히는 하나의 수퍼클래스와 여러 개의 믹스인을 배열로 지정할 수도 있다.
먼저, 단순한 클래스를 정의하는 예를 보면:
dojo.declare('Point', null, {
    x: 0,
    y: 0,
    constructor: function(x, y) {
        this.x = x || 0;
        this.y = y || 0;
    },
    moveTo: function(x, y) {
      this.x = x;
      this.y = y;
   },
    equals: function(point) {
      return (this.x == point.x) && (this.y == point.y);
    }
});

위의 예는 Point라는 이름의 클래스를 정의한다. 이 클래스는 수퍼클래스가 없으며, 하나의 생성자(constructor)와 x, y 두 개의 속성(멤버 변수)을 가지며, moveTo, equals 세 개의 메소드(멤버함수)를 가진다.
키워드는 declare(선언)이지만, 실제로 하는 일은 선언이 아니라 정의(define)다. 오히려 dojo.provide가 선언에 가깝다. 이 글의 주제에서 벗어나는 얘기니 궁금하면 구글신께 물어보시라... 나중에 시간나면 따로 쓰기로 하자~

이 클래스를 사용하는 예를 보면:
var p1 = new Point(1, 2);
var p2 = new Point();
p2.moveTo(3, 4);
alert(p1.equals(p2)); // false

보다시피 자바 등의 다른 언어와 별 차이가 없다.

계속해서, 상속의 예를 보면:
dojo.declare('Rect', [ Point ], {
    w: 0,
    h: 0,
    constuctor: function(x, y, w, h) {
       this.w = w || 0;
       this.h = h || 0;
    },
    getRight: function() {
      return x + w;
    },
    getBottom: function() {
      return y + h;
    },
    resize: function(w, h) {
      this.w = w;
      this.h = h;
    },
    equals: function(rect) {
      return this.inherited(arguments) && (this.w == w) && (this.h == h);
    }
});


위의 예는 Rect라는 이름의 클래스를 정의한다. 이 클래스는 Point를 상속받으며(x, y 두 개의 속성과 moveTo, equals 두 개의 메소드), 추가로 w, h 두 개의 속성과 getRight, getBottom, resize 세개의 메소드를 정의하며, equals를 오버라이딩(재정의)하고 있다.
equals에서 this.inherited(arguments)라는 생소한 구문이 보이는데 부모클래스에서 정의한 메소드를 호출하는 것이다. 자바로치면 super(rect)와 비슷하다고 보면 되겠다.
생성자에서 super를 호출하지 않는다는 점도 주의해야한다. 아무말 안해도 무조건 super를 호출한다. 자바스크립트는 함수 오버로딩(중복정의)을 지원하지 않기 때문에 생성자를 하나밖에 가질 수 없다.

객체 관련 유틸리티 함수들이 여러가지 있지만, 개인적으로 한 번이라도 써 본적이 있는 녀석들만 간단히 알아보면:
  • dojo.delegate(obj, { members...}) : 주어진 객체를 상속받은 객체를 만든다. dojo.declare와 달리, 클래스가 아니라 인스턴스 객체를 만든다. 간단하게 몇 가지 속성이나 메소드만 재정의한 객체를 만들때 편리하다.
  • dojo.clone(obj) : 주어진 객체의 deep-copy 객체를 만든다.
dojo는 하나 이상의 클래스를 하나의 .js 파일에 넣어두고, 이를 동적으로 로딩하는 기능을 제공하는데, dijit 설명할 때 자세히 알아보기로 하고... 여기서는 dojo 관련 소스들을 보다가 자주 보게될 함수 몇가지만 알아보자:
  • dojo.require(className) :  현재 모듈(나중에 설명한다)에서 주어진 이름의 클래스를 참조(사용)한다. 자바의 import와 비슷하지만, 자바와 달리 와일드카드(*)를 사용할 수 없다(dojo 0.4.x 쓰시던 분들도 주의!). 일반적으로 dojo.require('dijit.form.TextBox')라고 하면 dojo디렉토리/dijit/form/TextBox.js를 로딩한다고 이해해도 무방하다.
  • dojo.provide(className) : 주어진 이름의 클래스를 선언한다. 즉, 현재 모듈(나중에 설명한다)에서 주어진 이름의 클래스를 정의할 것임을 미리 알린다. 실제로는 빈 객체를 정의하기 때문에 네임스페이스 선언을 위해서 사용한다.
위의 두 함수는 dojo custom build에서도 매우 중요한 역할은 한다.

오늘은 여기까지~

다음에는 아기다리고기다리던 dijit(dojo widget)이다.

덧. 자바스크립트로 진지한 코딩을 해 본 개발자라면 IE의 trailing comma error의 공포를 알고 있을 것이다. dojo.delcare도 조심해서 쓰지 않으면 좌절을 맛보게 된다. 조만간 동의하실 것이라개인적으로 즐겨쓰는 방법은:
  1. 무조건! jslint로 검사한다. 예전에 썼던 웹 프로젝트에서 jslint로 자바스크립트 검증하기: maven 또는 ant 를 참조하시라~
  2. 무조건! 각 멤버 변수/함수를 쉼표로 끝내고, 불필요한 comma를 넣는 실수를 방지하기 위해 더미로 속성을 하나 더 넣는다. 예를 들면:
dojo.declare('Circle', [ Point ], {
    attr1: 'test',
    attr2: null,
    func1: function() {
        ...
    },
    func2: function() {
        ....
    },
    _dummy: null
});


댓글
댓글쓰기 폼