반응형
블로그 이미지
개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
솔웅

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리


반응형

Working with classes in Sencha Touch 2.0

1. Declaration (선언)

1.1. The Old Way (옛날 방법)


만약 여러분이 Sencha Touch 1.x 버전을 사용하신다면 분명 클래스를 생성하기 위한 Ext.extend 를 잘 알고 계실겁니다.

var MyPanel = Ext.extend(Object, { ... });

이것은 다른 클래스를 상속받는 새로운 클래스를 생성할 때 손쉽게 이용할 수 있는 방법입니다. 상속하는 것 말고는 다른 클래스 생성 관점에서 보면은 그렇게 크게 유용하지는 않습니다. configuration이라던지 statics, mixins 같은 것들 말이죠. 간단하게 이런 아이템들과 관련한 사항들을 살펴보죠.

아래 샘플을 한번 보세요.

My.cool.Panel = Ext.extend(Ext.Panel, { ... });

여기서는 새로운 클래스의 네임스페이스를 사용했고 Ext.Panel을 extend 했습니다. 이 예제에서는 두가지 알아두어야 할 것들이 있습니다.

1. My.cool은 프로퍼티로서 Panel을 할당하기 전에 객체로서 존재해 있어야 합니다.
2. Ext.Panel은 이것이 참조되기 전에 존재하고 또 로드 되어 있어야 합니다.

첫번째 아이템은 대개 Ext.namespace (Ext.ns)를 사용해서 해결 합니다. 이 메소드는 object/property를 통해 재귀적으로 참조 되고 그것이 존재하지 않으면 생성합니다. 좀 성가신 일은 여러분이 Ext.extend를 사용할 때는 항상 이것을 사용해야 한다는 것이죠. 아래 예제가 있습니다.

Ext.ns('My.cool');
My.cool.Panel = Ext.extend(Ext.Panel, { ... });


두번째 이슈는 이것을 address 하기가 쉽지 않다는 것입니다. 왜냐하면 Ext.Panel 은 다른 많은 클래스들을 depend on  할 것이기 때문이죠. 다른 클래스들을 직접적이든 간접적이든 상속하니까요. 그러면 그 상속할 대상이 되는 클래스는 반드시 존재해 있어야 하겠죠. 이러한 이유 때문에 Sencha Touch 2 이전에는 ext-all.js의 모든 라이브러리의 일부분만 사용해도 이것을 통재로 include 했었습니다.

1.2. The New Way (새로운 방법)

센차 터치 2 는 클래스를 생성할 때 오직 한가지 메소드만 생각하면 되도록 부가적인 것들은 전부 제거했습니다. 그것은 Ext.define 입니다. 아주 간단한 신택스죠.

Ext.define(className, members, onClassCreated);

이 신택스의 각 부분별로 한번 살펴 보겠습니다.

- className 은 클래스의 이름입니다.
- members는 key-value 조합의 클래스 멤버 collection을 나타내는 객체입니다.
- onClassCreated는 옵션입니다. 모든 관계된 클래스가 ready 되면 invoke 하기 위한 callback 함수이죠. 또한 이 클래스 자체가 완전히 생성되면 invoke 되기도 합니다. 클래서 생성의 새로운 비동기적인 성격으로 인해  이 callback은 다양한 경우에 아주 유용하게 사용될 수 있습니다. 이 내용은 Sencha Touch 2 튜토리얼 4장에서 다시 자세하게 다뤄질 겁니다.


Example

Ext.define('My.sample.Person', {
    name: 'Unknown',

    constructor: function(name) {
        if (name) {
            this.name = name;
        }
    },

    eat: function(foodType) {
        alert(this.name + " is eating: " + foodType);
    }
});

var aaron = Ext.create('My.sample.Person', 'Aaron');
    aaron.eat("Salad"); // alert("Aaron is eating: Salad");

   
Ext.create() 메소드를 사용해서 My.sample.Person의 새로운 인스턴스를 생성했습니다. 그러려면 아마 (new My.sample.Person())을 사용해야 했겠죠. 하지만 다이나믹 로딩의 장점을 이용하기 위해서 위의 방법대로 하실것을 권장합니다. 다이나믹 로딩의 좀 더 자세한 사항은 Getting Started guide를 살펴 보세요.

2. Configuration

센차터치 2에서는 클래스가 생성되기 전에 강력한 Ext.Class 전처리 장치에 의해 진행되는 config property를 제공하고 있습니다.
이것은 아래와 같은 내용들을 제공합니다.

- configurations는 다른 클래스 멤버로부터 완전하게 캡슐화 되어있습니다.
- 각 config property의 getter와 setter 메소드들은 클래스가 생성되는 동안 이 메소드들이 따로 정의되어 있지 않으면 class prototype에 자동적으로 생성합니다.
- 각 config property에 대해 apply 메소드도 또한 생성됩니다. 자동으로 생성된 setter 메소드는 value를 setting 하기 전에 내부적으로 apply 메소드를 call 합니다.
그 value 를 세팅하기 전에 custom logic 을 run 할 필요가 있으면 config property에 apply 메소드를 override 합니다. 만약 apply가 어떤 값도 return 하지 않으면 setter는 value를 set 하지 않습니다.

아래에 예제가 있습니다.

Ext.define('My.own.WindowBottomBar', {});

Ext.define('My.own.Window', {

    /** @readonly */
    isWindow: true,

    config: {
        title: 'Title Here',

        bottomBar: {
            enabled: true,
            height: 50,
            resizable: false
        }
    },

    constructor: function(config) {
        this.initConfig(config);
    },

    applyTitle: function(title) {
        if (!Ext.isString(title) || title.length === 0) {
            console.log('Error: Title must be a valid non-empty string');
        }
        else {
            return title;
        }
    },

    applyBottomBar: function(bottomBar) {
        if (bottomBar && bottomBar.enabled) {
            if (!this.bottomBar) {
                return Ext.create('My.own.WindowBottomBar', bottomBar);
            }
            else {
                this.bottomBar.setConfig(bottomBar);
            }
        }
    }
});


아래 예제는 이것을 어떻게 사용하는지를 보여줍니다.

var myWindow = Ext.create('My.own.Window', {
    title: 'Hello World',
    bottomBar: {
        height: 60
    }
});

console.log(myWindow.getTitle()); // logs "Hello World"

myWindow.setTitle('Something New');
console.log(myWindow.getTitle()); // logs "Something New"

myWindow.setTitle(null); // logs "Error: Title must be a valid non-empty string"

myWindow.setBottomBar({ height: 100 }); // Bottom bar's height is changed to 100



3. Statics

static 멤버들은 static config를 사용해서 정의될 수 있습니다.

Ext.define('Computer', {
    statics: {
        instanceCount: 0,
        factory: function(brand) {
            // 'this' in static methods refer to the class itself
            return new this({brand: brand});
        }
    },

    config: {
        brand: null
    },

    constructor: function(config) {
        this.initConfig(config);

        // the 'self' property of an instance refers to its class
        this.self.instanceCount ++;
    }
});

var dellComputer = Computer.factory('Dell');
var appleComputer = Computer.factory('Mac');

alert(appleComputer.getBrand()); // using the auto-generated getter to get the value of a config property. Alerts "Mac"

alert(Computer.instanceCount); // Alerts "2"



Error Handling and debugging (에러 처리와 디버깅)


센차터치 2에는 디버깅과 에러 처리를 도와주는 유용한 기능이 있습니다.

메소드의 display name을 얻으려면 Ext.getDisplayName()을 사용하실 수 있습니다. 이것은 description 안에 클래스 이름과 메소드 이름을 가진 에러를 throw 할 때 유용하게 사용하실 수 있습니다.

throw new Error('['+ Ext.getDisplayName(arguments.callee) +'] Some message here');

에러가 Ext.define()을 사용해 정의된 클래스의 메소드내에서 던져졌을 때 여러분의 브라우저가 크롬(Chrome)이나 사파리(Safari) 같이 WebKit 을 사용하는 브라우저라면 call stack에 그 메소드와 클래스 이름이 표시될 겁니다.

아래에 크롬에서 보실 수 있는 에러 메세지들이 있습니다.


반응형