您的位置:首页 > Web前端 > JavaScript

js框架开发之旅--对父类的访问

2013-10-15 11:41 239 查看
上一章我们讨论了基于原型的继承和基于类的继承。这一章我们继续介绍如何实现面向对象的js,我们要阐述turing.oo的原理,并且尝试去实现super方法。

更深层次的类的创建

Turing的方法Class.create方法创建一个类,使用new创建的过程中会调用初始化方法。方法非常简单:

create: function() {
var methods = null,
parent  = undefined,
klass   = function() {
this.initialize.apply(this, arguments);
};


apply看上去很神奇,但是有些人不太喜欢他,因为它使用复杂不利于封装。上面的例子,我们在类的构造函数中调用初始化方法,并使用this和arguments作为参数。this表示将方法绑定到新创建的实例上执行,arguments代表你给构造函数传递的所有参数。

根据上面的代码,所有的创建的类都应该有一个默认的初始化方法。如果你不需要在初始化的时候做什么,你可以定义一个简单的空方法:
if (!klass.prototype.initialize)
klass.prototype.initialize = function(){};


语法技巧

在我们的类里继承其他对象是一个非常有用的技巧。语法如下:

var MixinUser = turing.Class({
include: User,
initialize: function(log) {
this.log = log;
}
});


引入对象应该遵守一定的规则,以便让代码有一个统一的规范。
方法必须从指定的类里继承
initialize方法不能被覆盖
可以继承多个对象
如果你使用turing.oo.create创建了类,你的类里继承了引入的方法。为了保持代码的可读性,我们没有在create里进行属性继承,我们使用了一个新的方法mixin。我们尝试写一下符合上面规则的伪代码:

mixin: function(klass, things) {
if "there are some valid things" {
if "the things are a class" {
"use turing.oo.extend to copy the methods over"
} else if "the things are an array" {
for "each class in the array" {
"use turing.oo.extend to copy the methods over"
}
}
}
},


父类

之前我们提到了Prototype的super功能。Prototype允许类通过addMethods扩展方法,相同名称的方法会被覆盖,但是我们仍然可以通过$super来方法父类的方法。

下面的例子,我们创建了User类,并且通过继承User类创建了SuperUser:

var User = turing.Class({
initialize: function(name, age) {
this.name = name;
this.age  = age;
},

login: function() {
return true;
},

toString: function() {
return "name: " + this.name + ", age: " + this.age;
}
});

var SuperUser = turing.Class(User, {
initialize: function() {
// Somehow call the parent's initialize
}
});


我们测试上面的代码:
given('an inherited class that uses super', function() {
var superUser = new SuperUser('alex', 104);
should('have run super()', superUser.age).equals(104);
});


我们还没有实现super,执行结果如下:
Given an inherited class that uses super
- should have run super(): 104 does not equal: undefined


上面的代码说明新的初始化方法覆盖了父类的方法。现在我们想要调用父类的初始化方法,这里再次使用了apply。
var SuperUser = turing.Class(User, {
initialize: function() {
User.prototype.initialize.apply(this, arguments);
}
});


代码看上去还不太完美,许多语言的super的实现都比较简单,让用户通过apply来实现super的调用确实不太友好。最好的办法就是在父类的原型中实现super方法,把上面的代码封装起来。
var SuperUser = turing.Class(User, {
initialize: function() {
this.$super('initialize', arguments);
},

toString: function() {
return "SuperUser: " + this.$super('toString');
}
});


这样的代码看上去简单多了并且便于理解。

结论

我们现在已经实现了一个简单,可读的面向对象的类。我们以后的架构都是基于这个类实现的。我希望通过最近的两篇文章,能让你感受到js的简单和灵活。




牧客网--让自由职业成为一个靠谱的工作
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息