JS.Class - 3. Modules & Mixins


Mixins 允许开发人员在不做继承和修改的情况下,为类型添加额外的方法。这有点像 C# 的扩展方法,但动态语言 Mixins 机制要更加灵活。记得我最初看 Ruby 的时候就被这个功能吸引过。在使用 Mixins 之前,我们需要先定义一个 Modules,它是这些扩展方法的载体和容器。

var Module = new JS.Module(
{
  extend :
  {
    println : function(s) { document.writeln(s + "<br />"); }
  },
  
  getName : function() 
  {
    return this.hasOwnProperty("name") ? this.name : this.toString();
  }
});
var User = new JS.Class(
{
  name : "User",
  include : Module
});
var o = new User();
o.name = "Tom";
User.println(o.getName());

  我们可以使用 JS.Module 来创建一个 Module,它可以包含静态和实例两种扩展方法,是不是很强?不过需要注意,Module 无法实例化,也无法在外部调用其静态方法。下面两种写法都会引发异常。

new Module();
Module.println("ab");

  除了在目标类型使用 include 引入一个或多个 (include : [Module1, Module2]) Module 外,我们还可以直接在外部动态引入 (对已经生成的对象实例同样有效)。

var User = new JS.Class(
{
  name : "User"
});
User.include(Module);

  Minxins 会重写 (overwrite) 类型或对象实例中的同名方法。

var Module = new JS.Module(
{
  extend :
  {
    println : function(s) { document.writeln("Mixins: " + s + "<br />"); }
  },
  
  test : function() 
  {
    return "[Mixins]";
  }
});
var User = new JS.Class(
{
  test : function() 
  {
    return "[User]";
  },
  extend :
  {
    println : function(s) { document.writeln("User: " + s + "<br />"); }
  }
});
var o = new User();
User.println(o.test()); // User: [User]
User.include(Module);
User.println(o.test()); // Mixins: [Mixins]

  要避免这种情况发生,可以使用 "include(Module, false)" 。

  附注: 我使用的 1.6 版本这个参数没有起作用,似乎是个 Bug,overwirte 参数在 class.js 183 行传递过程中丢失。另外作者提到 "include 引入实例方法,extend 引入静态方法" 的说法似乎也有些问题。

  JS.Class 提供了一种 Hook 机制,当一个类型被 subclassed 或 Mixins 时,类型中特定名称的静态方法将被触发。

var User = new JS.Class(
{
  extend :
  {
    inherited : function(klass) { alert("onInherited!"); },
    included : function(klass) { alert("onIncluded!"); },
    extended : function(klass) { alert("onExtended!"); }
  }
});
var Manager = new JS.Class(User, {});
User.include(Module);
User.extend(Module);


« 
» 
快速导航

Copyright © 2016 phpStudy | 豫ICP备2021030365号-3