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

上一章我们讨论了基于原型的继承和基于类的继承。这一章我们继续介绍如何实现面向对象的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的简单和灵活。


牧客网--让自由职业成为一个靠谱的工作


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值