sencha类系统(二)-processors

   此文接sencha类系统(一)

   原译文地址:Sencha Class System processors

类继承

为了让类A继承类B,可以在定义A是为classMembers对象添加extend属性,属性值为‘B'

上代码:

Ext.define(‘My.sample.Developer’,{
extend:’My.sample.Person’,
code:function (language) {
alert(this.name+’is coding in ‘+language);
},
});
var tommy=new My.sample.Developer(‘tommy’);
tommy.walk(5);
tommy.code(‘JavaScript’);


上例中My.sample.Person用单引号引起来了,这是标准的写法。使用字符串类型的类名,你不需要考虑关于依赖的问题,因为Ext.Loader在它们不存在的时候动态的加载它们。两个引号为我们的编程带来了极大的好处。

可以在重写方法中使用this.callParent调用父类中被重写重写的方法,接着上面的例子我们重写Person类的walk方法。

// My/sample/Developer.js
Ext.define('My.sample.Developer', {
    extend: 'My.sample.Person'   code: function(language) { /* … */ },   walk: function(steps) {
        if (steps > 100) {
            alert("Are you serious? That's too far! I'm lazy…");
        }
        else {
            return this.callParent(arguments);
        }
    }
});   // app.js
var tommy = new My.sample.Developer('Tommy');   tommy.walk(50);    // alerts "Tommy is walking 50 steps"
tommy.walk(101);   // alerts "Are you serious? That's too far! I'm lazy…"


我们将walk接受的参数直接传递给父类的的walk方法,当然这不是必须的,比如就可以this.callParent([50]),但是参数必须是数组或arguemtns

Class Mixins

Mixins是一组可以在类间共享的具有重用性的features。称为ablities可能会更恰当。在Sencha中mixins只是简单的类。任何类都可以使用mixins,senha中有一些关于mixins很好的例子:

Identifiable,赋予目标类一个getId方法成成唯一ID

Observable,赋予目标类事件处理的能力

Traversable,赋予目标类tree-like API

一个类可以拥有多于一个的mixin,让类A中混合进类B和类C,可以在定义类A时添加mixins属性,属性值为一个描述 B和C的对象。为了形象的说明mixins的好处,我们定义三个类代表一个人可以拥有的三种不同能力,命名为:

CanSing

CanPlayGuitar

CanComposeSongs

然后我们创建一个CoolGuy类和一个Musician方法。一个CoolGuy可以CanSing和CanPlayGuitar,一个Musician可以CanPlayGuitar和CanComposeSongs,CanSing。

// My/sample/CanSing.js
Ext.define('My.sample.CanSing', {
    sing: function(songName) {
        alert("I'm singing " + songName);
    }
});   // My/sample/CanPlayGuitar.js
Ext.define('My.sample.CanPlayGuitar', {
    playGuitar: function() {
        alert("I'm playing guitar");
    }
});   // My/sample/CanComposeSongs.js
Ext.define('My.sample.CanComposeSongs', {
    composeSongs: function() {
        alert("I'm composing songs");   return this;
    }
});   // My/sample/CoolGuy.js
Ext.define('My.sample.CoolGuy', {
    extend: 'My.sample.Person',
    mixins: {
        canSing: 'My.sample.CanSing',
        canPlayGuitar: 'My.sample.CanPlayGuitar'
    }
});   // My/sample/Musician.js
Ext.define('My.sample.Musician', {
    extend: 'My.sample.Person',
    mixins: {
        canSing: 'My.sample.CanSing',
        canPlayGuitar: 'My.sample.CanPlayGuitar',
        canComposeSongs: 'My.sample.CanComposeSongs'
    }
});   // app.js
var nicolas = new My.sample.CoolGuy("Nicolas");
nicolas.sing("November Rain"); // alerts "I'm singing November Rain"


 
mixins是通过键值对声明的,key可以用来引用被类重写的mixins方法。上代码:
// My/sample/CoolGuy.js
Ext.define('My.sample.CoolGuy', {
    extend: 'My.sample.Person',
    mixins: {
        canSing: 'My.sample.CanSing',
        canPlayGuitar: 'My.sample.CanPlayGuitar'
    },   sing: function() {
        alert("Attention!");   // this.mixins is a special object holding references to all mixins' prototypes
        return this.mixins.canSing.sing.apply(this, arguments);
    }
});   // app.js
var nicolas = new My.sample.CoolGuy("Nicolas");
nicolas.sing("November Rain"); // alerts "Attention!"
                               // alerts "I'm singing November Rain"


此外,因为我们在mixins中使用了字符串类型的类名,所以这些类也会在需要的时候自动加载。
 
Class Configuration
这是Ext JS 4.1+和sencha touch 2.0+才有的特性。Ext JS 4.0并没有使用。
通过在类声明对象的config对象属性,可以定义类的公共API。config中的每一个配置项在没有自己声明getter和setter时都会有自己自动生成的setter和getter方法。
举例如下:
Ext.define('My.sample.Person', {
    config: {
        name: 'Mr. Unknown',
        age: 0,
        gender: 'Male'
    },
 
    constructor: function(config) {
        this.initConfig(config);
 
        return this;
    }
 
    /* … */
});


通过config在Person类的定义中添加name,age,gender项:
在类中,this.name指向默认值’Mr. Unknown’,但是可以通过使用setter和getter方法来进行更安全的访问。
var jacky = new Person({
    name: "Jacky",
    age: 35
});
 
alert(jacky.getAge());      // alerts 35
alert(jacky.getGender());   // alerts "Male"
 
jacky.walk(10);             // alerts "Jacky is walking 10 steps"
 
jacky.setName("Mr. Nguyen");
alert(jacky.getName());     // alerts "Mr. Nguyen"
 
jacky.walk(10);  // alerts "Mr. Nguyen is walking 10 steps"


我们在contructor中调用this.initConfig,并将config传递做参数,这期间有两个很重要的操作:

对象实例化时的config对象与默认的config对象合并;(这段原文我也没有理解的很好,大家可以参照原文)

所有相关属性的setter方法被调用,参数是合并后的值。

除了可以保存相应的值外,框架内的setters还有两个艰巨的任务:

在真正设置值前,过滤/验证/转换提供的参数值。

当值被设置或变化后,通知/post-processing

为了让这种模式更加标准化,自动生成的setters提供了另外两个模板函数供重写,比如config中的foo项就会有applyFoo和updateFoo方法,前者在设置值之前执行,后者在值设置之后执行。这样我们使用这种方法可以完善上面我们的例子,比如age属性明显只能是数字。

Ext.define('My.sample.Person', {
    config: { /* … */ },
 
    constructor: { /* … */ }
 
    applyAge: function(age) {
        if (typeof age != 'number' || age < 0) {
            console.warn("Invalid age, must be a positive number");
            return;
        }
 
        return age;
    },
 
    updateAge: function(newAge, oldAge) {
        // age has changed from "oldAge" to "newAge"
        this.fireEvent('agechange', this, newAge, oldAge);
    }
 
    /* … */
});
 
var jacky = new Person({
    name: "Jacky",
    age: 'invalid'
});
 
alert(jacky.getAge());      // alerts 0
 
alert(jacky.setAge(-100));  // alerts 0
alert(jacky.getAge());      // alerts 0
 
alert(jacky.setAge(35));    // alerts 0
alert(jacky.getAge());      // alerts 35


 
所以当使用config属性时,不应该自己定义setter和getter,相反应该重写apply*和update*方法,你的代码中应该只包含应该有的逻辑。
 
类依赖(Class  Dependencies)
在一个类的方法中使用另外一个类的场景很常见。想让Ext.Loader知道我们的类依赖,只需要在类定义时声明数组类型的requires属性。上代码:
Ext.define('My.sample.Person', {
    requires: ['My.sample.Validator', 'My.sample.Formatter'],
 
    /* … */
 
    applyAge: function(age) {
        if (!My.sample.Validator.validateAge(age)) {
            console.warn("Invalid age, must be a positive number");
            return;
        }
 
        return age;
    },
 
    applyName: function(name) {
        return My.sample.Formatter.capitalize(name);
    }
 
    /* … */
});


 
Post-processors:


Singleton
在Ext JS中,Singleton是一个类只有一个实例。将类声明中的singleton设为true,即可在类创建结束后创建一个类实例,然后赋值给命名空间对象的相应属性。
上代码:
Ext.define('My.sample.Validator', {
    singleton: true,
 
    validateNumber: function(number) {
        return typeof number == 'number';
    }
 
    validateAge: function(number) {
        return this.validateNumber(number) && number >= 0;
    }
 
    /* … */
});

alert(My.sample.Validator.validateNumber('invalid')); // alerts false
上面的My.sample.Validator是一个类实例,而不是一个类。可以使用Ext.getClass获取实例的类。
  var ValidatorClass = Ext.getClass(My.sample.Validator);
 
Alternative Class Names
有时候为了为了方便或向下兼容,会为类创建别名。这是可以使用alternateClassName属性。属性可以是一个字符串(一个名字),字符串数组(多个名字)
Ext.define('My.sample.form.Field', {
    alternateClassName: ['My.FormField', 'My.sample.FormField']
 
    /* … */
});
 
// My.sample.form.Field, My.FormField and My.sample.FormField now reference the same class


 
总结
sencha类系统是在Senha  Javascript框架中使用面向对象编程的不二选择。现在它已经很稳定,可以在代码中使用它。我们会不断改进类系统以减轻你日复一日重复编程……。(最后就是吹吹牛,讲讲口号微笑
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值