扩展外设对象

Ruff 驱动的一个基本设计原则是,只做基本功能。比如,灯的驱动只提供开关的函数,以及一个查询方法。

$('#led').turnOn();
$('#led').turnOff();
$('#led').isOn();

但是,如果你有扩展需求该怎么办?比如,我希望有个 toggle 函数:当灯亮时,关掉它,如果灯关着,则打开它。

使用 extend

在 Ruff 里面,每个设备对象都有一个 extend 函数,用来扩展设备对象本身:

$('#led').extend({
toggle: function() {
if (this.isOn()) {
this.turnOff();
} else {
this.turnOn();
}
}
});

传给 extend 是一个普通 JavaScript 对象,其中定义的函数会直接挂载在设备对象上,所以,这里可以使用 this 访问设备对象的函数。

定义 trait

toggle 是一个常见的函数,可以在很多的设备对象上都可以使用。如果我们想把它当做一个通用的函数,在多个项目中使用,我们把它定义成一个模块。但是,如何才能保证使用目标对象上有必需的函数呢?我们可以把它定义成一个 trait

trait 是一个常见的语言特性,用于扩展对象行为。Ruff 的 SDK 里提供了对 trait 的支持。

在这个例子里面,我们需要定义一个 trait,它有一个 toggle 函数,并且需要对象上有 turnOnturnOff 以及 isOn 函数。

我们可以这样定义 toggle 的 trait,

var trait = require('trait');

var ToggleTrait = trait({
toggle: function() {
if (this.isOn()) {
this.turnOff();
} else {
this.turnOn();
}
},

turnOn: trait.required,
turnOff: trait.required,
isOn: trait.required
});

trait 的参数一个是普通的 JavaScript 对象,其中,

  • 普通的 JavaScript 函数会成为一个目标对象的成员函数
  • 标记为 trait.required 的函数,则用来检查目标对象是否包含该函数

有了这个 trait,就可以用它扩展设备对象,extend 方法是支持 trait 的:

$('#led').extend(ToggleTrait);

如果设备对象不包含必需的方法,则会报错。

我们也可以把这个 trait 做成一个独立的模块发布到 Rap 软件仓库