在dojo工具箱中,dojo/_base/declare模块是创建类的基础。declare允许开发者实现类多继承,从而创建有弹性的(灵活的)代码,避免写重复的代码。Dojo,Digit,Dojox模块都使用了declare。
- 语法declare(classname,superclass,props);
1 参数解释:classname:类名,superclass:父类名,props:属性。注意:如果不继承父类,需要给父类参数指定null。
2 多继承的时候,多个父类需要写在列表中。 - 示例:
//定义基类Person declare("Person", null,{ name:null, age:null, constructor: function(args){ this.name = args.name; this.age = args.age; }, getName:function(){ return this.name; }, getAge:function(){ console.log(this.age); } }); })
2.1 单继承:
下面定义了Employee类和Shareholder类,它们都继承于Person类。Employee类添加了workExperience属性,并重写了Person类中的getName方法,同时添加了getWorkExperience和getInput方法。
Shareholder类添加了share属性,并添加了getShare:function方法。//下面定义了类Employee,其继承于Person类 declare("Employee", Person,{ workExperience:null, constructor: function(args){ this.workExperience = args.workExperience; }, getWorkExperience:function(){ console.log(this.workExperience); }, getName:function(){ return "Employee:"+this.name; }, getSalary:function(){ return 5000; } }) var employee1 = new Employee({name:"peter",age:"27",workExperience:"4"}); employee1.getWorkExperience(); //4 employee1.getName(); //Employee:peter employee1.getAge(); //27 调用父类中的方法
可以看到在Employee的实例中,我们能够调用父类中定义的方法。而在类的constructor初始化方法中,我们并没有调用父类相关的方法,但是我们成功初始化了name和age两个属性,这是因为dojo会自动调用父类的初始化方法,完成继承要求的相关初始化工作。
2.2 多继承
dojo支持多继承的功能。使用dojo的多继承功能时,需要注意的是:只有数组中的第一个元素会作为真正的父类,而其它的元素则是通过mixin的方式进行属性添加以构建原型链的。
例如,这里定义了一个类表示股票持有者,而公司中的员工也可能会持有股票,因此定义了一个ShareholderEmployee来表示这个群体,该类继承于Shareholder类和Employee类。//下面定义了Shareholder类,继承于Person类 declare("Shareholder", Person,{ share:null, constructor: function(args){ this.share = args.share; }, getShare:function(){ return this.share; } }); //下面定义了类ShareholderEmployee,其继承于Employee和Shareholder类 declare("ShareholderEmployee", [Employee,Shareholder],{ getInfo:function(){ console.log("I'm an Employee with stock.My share is "+this.getShare()+"."+"My name is "+this.getName()+"."); } }); var shareholderEmployee1 = new ShareholderEmployee({name:"levin",age:30,workExperience:4,share:300}); shareholderEmployee1.getInfo(); //I'm an Employee with stock.My share is 300.My name is Employee:levin.
至此,我们通过多继承的方式实现了一个类用来描述持有股票的员工。
2.3 子类调用父类方法
在编程中,我们经常会遇到在子类的某个方法中需要调用父类的方法来协作完成功能。例如,我们又定义了一个名为Manager的类,该类继承自Employee类,并重写getInput方法,Manager的收入分为两部分,一部分是与 Employee相同的固定收入,另一部分是与管理经验相关的其它收入,这样在定义Manager的时候,就需要调用父类的方法。可以使用this.inherited(arguments)语句调用父类的同名方法。例如:declare("Manager", Employee,{ manageExperience:null, constructor: function(args){ this.manageExperience = args.manageExperience; }, getSalary:function(){ var fromBase = this.inherited(arguments); return fromBase+1000*this.manageExperience; } }) var manager = new Manager({name:"levin",age:30,workExperience:4,manageExperience:2}); console.log(manager.getSalary()); //7000
从以上代码可以看到,通过inherited方法的使用,使得Manager可以调用父类的方法。 - 关于原型继承
类声明中可以给原始类型(number, string, boolean) 定义默认的值, 然后在实例对像中可以直接修改。 但是,如果你给原型上的属性分配的是一个对象(Object, Array), 那么每一个实例会共享同一个值。在实例中修改会在原型中体现出来。
例如,定义了一个Student类:declare("Student",null,{ name:"jack", age:"13", favoriteColor:["red","black","green"] })
该类中包含了三个属性,两个原始类型属性:name(string类型)、age(number类型),一个对象类型:favoriteColor(array类型)。
var stu1 = new Student();
var stu2 = new Student();
console.log(stu1.name===stu2.name); //true
stu2.name = 'rose';
console.log(stu1.name===stu2.name); //false
console.log(stu1.age===stu2.age); //true
console.log(stu1.age); // 13
对Student类实例化得到两个对象stu1和stu2,可以对实例对象中基本类型的属性进行修改,而这并不会影响到原型对象。
![图片标题 图片说明](https://img-blog.csdnimg.cn/img_convert/c69818941bec3f738570d1871821ff10.png)
而当我们在实例中对对象类型的属性进行修改时,这会修改原型中的属性:
console.log(stu1.favoriteColor===stu2.favoriteColor); //true
stu2.favoriteColor.push("yellow","blue");
console.log(stu1.favoriteColor===stu2.favoriteColor); //true
console.log(stu1.favoriteColor); //["red", "black", "green", "yellow", "blue"]
console.log(stu2.favoriteColor); //["red", "black", "green", "yellow", "blue"]
可以看到此时的原型中favorite属性已被修改:
![图片标题 图片说明](https://img-blog.csdnimg.cn/img_convert/bf4e82cd90e35cb1dad74b64b3af772c.png)
为了避免非故意的修改共享的数组或者对象, 对象的属性应该声名为null 然后在构造函数中对它初始化。
declare("Student",null,{
name:null,
age:null,
favoriteColor:null,
score:null,
constructor:function(name,age){
this.name = name;
this.age = age;
this.favoriteColor = [];
this.score = {};
}
})
stu3 = new Student("Rose","12")
stu3.favoriteColor = ["red","black","green"];
stu3.score = {"语文":90,"数学":93}
console.log(stu3);
输出结果:
![图片标题 图片说明](https://img-blog.csdnimg.cn/img_convert/1de96ba8d54ff3efbf25fbbf0ddec874.png)