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的簡單和靈活。


牧客網--讓自由職業成爲一個靠譜的工作


發佈了16 篇原創文章 · 獲贊 87 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章