dojo/_base/declare模块是Dojo Toolkit中创建类的基础。declare允许使用多重继承为开发者创建灵活的代码,而且避免编写相同代码的过程。Dojo,Dijit和Dojox模块都使用declare。在这个教程你将知道为什么要使用它。
Getting Started
确保你复习了上一节的内容
Basic Dojo Class Creation with Dojo(创建基本的Dojo类)
declare 函数在dojo/_base/declare模块中定义。 declare 接受三个参数: className, superClass, and properties.
ClassName
className代表类的名字,而且包含命名空间。被命名的类被放置在全局范围内,className也可以通过命名空间代表类的继承链。
Named Class(命名类)
1
2
3
4
|
// Create a new class named "mynamespace.MyClass"
declare(
"mynamespace.MyClass"
,
null
, {
// Custom properties and methods here
});
|
一个名为mynamespace.MyClass的类已经可以在程序的全局中使用了。
如果类是用于Dojo parser的,则必须给类命名。其他所有类应该忽略className参数。
"Anonymous" Class(匿名类)
1
2
3
4
5
6
|
// Create a scoped, anonymous class
var
MyClass = declare(
null
, {
// Custom properties and methods here
});
|
MyClass现在可以在当前范围内使用。
SuperClass(es)(超类(或者多个))
superClass参数可以是null,单个存在的类或多个存在的类数组。如果一个新类继承多个类,第一个类将作为继承属性,其余的视为混入。
Class with No Inheritance(不继承的类)
1
2
3
4
5
|
var
MyClass = declare(
null
, {
// Custom properties and methods here
});
|
null代表没有从其他类继承。
Class Inheriting from Another Class(从其他类继承的类)
1
2
3
4
|
var
MySubClass = declare(MyClass, {
// MySubClass now has all of MyClass's properties and methods
// These properties and methods override parent's
});
|
新的MySubClass类将继承MyClass类的属性和方法。通过为daclare的第三个参数添加新的键值和定义将重写超类的属性或方法,我们马上解释它。
Class with Multiple Inheritance(多重继承的类)
1
2
3
4
5
6
7
8
9
10
|
var
MyMultiSubClass = declare([
MySubClass,
MyOtherClass,
MyMixinClass
],{
// MyMultiSubClass now has all of the properties and methods from:
// MySubClass, MyOtherClass, and MyMixinClass
});
|
一个类的数组代表多重继承。属性和方法是从左到右继承的,数组的第一个类作为基础属性,其余类混入这个类中。
如果多个超类都指定了一个同名的属性或方法,将使用最后的超类的属性或方法。
Properties and Methods Object(对象的属性和方法)
最后一个daclare的参数是一个包含属性和方法的对象,它作为类的原型。这个参数提供的属性和方法将重写超类中同名的属性或方法。
Custom Properties and Methods(自定义属性和方法)
1
2
3
4
5
6
7
8
9
10
11
|
// Class with custom properties and methods
var
MyClass = declare(MyParentClass, {
// Any property
myProperty1: 12,
// Another
myOtherProperty:
"Hello"
,
// A method
myMethod:
function
(){
// Perform any functionality here
returnresult;
} });
|
Example: Basic Class Creation and Inheritance(示例:基本的类创建和继承)
下面的代码创建了一个从dijit/form/Button继承的widget:
1
2
3
4
5
6
7
8
9
10
11
12
|
define([
"dojo/_base/declare"
,
"dijit/form/Button"
],
function
(declare, Button){
return
declare(
"mynamespace.Button"
, Button, {
label:
"My Button"
,
onClick:
function
(evt){
console.log(
"I was clicked!"
);
this
.inherited(arguments);
}
});
});
|
从上面的片段我们可以推断:
-
类名是mynamespace.Button。
-
类可以使用全局的mynamespace.Button或模块的返回值来引用。
-
它继承dijit/form/Button (和button的依赖项)。
-
这个类定义了属性和方法。
让我们来学习constructor方法更深入挖掘类的创建。
The constructor Method(constructor方法)
特殊方法之一是constructor。constructor在类实例化后被触发,它在新对象中执行,这意味着this关键词引用的是实例而不是类。constructror方法接受任意数目的实例特定的参数。
// Create a new class
var Twitter = declare(null, {
// The default username
username: "defaultUser",
// The constructor
constructor: function(args){
declare.safeMixin(this,args);
}
});
实例化它:
1
|
var
myInstance = newTwitter();
|
因为没有指定实例的设置,username默认为"defaultUser"。为了利用safeMinxin方法,我们提供username参数。
1
2
3
|
var
myInstance =
new
Twitter({
username:
"sitepen"
});
|
现在实例使用sitepen作为username的设置。
在创建和继承类中declare.safeMixin同样很有用。下面引用一段API文档的陈述:
这个函数用来混合属性,有点像lang._mixin做的事,但是它读取一个constructor属性和装饰函数,又像dojo/_base/declare的工作。这意味着它是与类和dojo/_base/declare制造的对象一起使用的。一个函数混入了declare.safeMixin也可使用 this.inherited()函数就像普通函数一样。这个函数用于实现constructor的extend()方法。
Inheritance(继承)
如上所述,declare第二个参数是继承的定义。类是从左到右混入的,后面的类的方法和属性会覆盖前面的。做一个演示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
// Define class A
var
A = declare(
null
, {
// A few properties...
propertyA:
"Yes"
,
propertyB: 2
});
// Define class B
var
B = declare(A, {
// A few properties...
propertyA:
"Maybe"
,
propertyB: 1,
propertyC:
true
});
// Define class C
var
C = declare([mynamespace.A, mynamespace.B], {
// A few properties...
propertyA:
"No"
,
propertyB: 99,
propertyD:
false
});
|
继承类的属性结果是:
1
2
3
4
5
6
7
|
// Create an instance
var
instance =
new
C();
// instance.propertyA = "No" // overridden by B, then by C
// instance.propertyB = 99 // overridden by B, then by C
// instance.propertyC = true // kept from B
// instance.propertyD = false // created by C
|
number,string和boolean变量是可以直接设置和重定义的。注意当使用数组和对象在dojo/_base/declare中,确保它们的范围是正确的。数组和对象在return中定义将被所有实例对象共享使用。在constructor中定义是每个实例的属性。参考文档dojo/_base/declare获得额外的信息。
this.inherited
虽然重定义方法确实有用,但有时候每个类的构造函数通过继承链应该被执行保护其原始的功能。这就需要用到this.inherited(arguments)语句,它调用父类中同名的方法。考虑下面的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
// Define class A
var
A = declare(
null
, {
myMethod:
function
(){
console.log(
"Hello!"
);
}
});
// Define class B
var
B = declare(A, {
myMethod:
function
(){
// Call A's myMethod
this
.inherited(arguments);
// arguments provided to A's myMethod
console.log(
"World!"
);
}
});
// Create an instance of B
var
myB =
new
B();
myB.myMethod();
// Would output:
// Hello!
// World!
|
this.inherited方法可以在任何时候在子类中被调用。有时候你想去调用inherited()在子函数中间甚至在最后。也就是说,你不应该在constructor里调用它。
Conclusion(结论)
declare是创建模块化、可重用类的关键。declare允许创建多重继承的复杂类以及任意数量的属性和方法。更好的是declare容易学习,它将避免开发者重复代码。