sencha类系统(二)-processors

来源:互联网 发布:latex有windows版么 编辑:程序博客网 时间:2024/06/05 19:15

   此文接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.jsExt.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.jsvar 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.jsExt.define('My.sample.CanSing', {    sing: function(songName) {        alert("I'm singing " + songName);    }});   // My/sample/CanPlayGuitar.jsExt.define('My.sample.CanPlayGuitar', {    playGuitar: function() {        alert("I'm playing guitar");    }});   // My/sample/CanComposeSongs.jsExt.define('My.sample.CanComposeSongs', {    composeSongs: function() {        alert("I'm composing songs");   return this;    }});   // My/sample/CoolGuy.jsExt.define('My.sample.CoolGuy', {    extend: 'My.sample.Person',    mixins: {        canSing: 'My.sample.CanSing',        canPlayGuitar: 'My.sample.CanPlayGuitar'    }});   // My/sample/Musician.jsExt.define('My.sample.Musician', {    extend: 'My.sample.Person',    mixins: {        canSing: 'My.sample.CanSing',        canPlayGuitar: 'My.sample.CanPlayGuitar',        canComposeSongs: 'My.sample.CanComposeSongs'    }});   // app.jsvar nicolas = new My.sample.CoolGuy("Nicolas");nicolas.sing("November Rain"); // alerts "I'm singing November Rain"


 
mixins是通过键值对声明的,key可以用来引用被类重写的mixins方法。上代码:
// My/sample/CoolGuy.jsExt.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.jsvar 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 35alert(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 0alert(jacky.getAge());      // alerts 0 alert(jacky.setAge(35));    // alerts 0alert(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框架中使用面向对象编程的不二选择。现在它已经很稳定,可以在代码中使用它。我们会不断改进类系统以减轻你日复一日重复编程……。(最后就是吹吹牛,讲讲口号微笑