第一版是为 Lua 5.0 编写的。虽然在很大程度上仍然适用于更高版本,但还是有一些差异。
第四版针对 Lua 5.3,可在 Amazon 和其他书店购买。
购买本书还可以帮助 支持 Lua 项目。
用 Lua 编程 | ||
第二部分。表和对象 第 16 章。面向对象编程 |
Lua 中的表在多个方面都是对象。与对象类似,表具有状态。与对象类似,表具有独立于其值的标识(“自性”);具体而言,具有相同值的两个对象(表)是不同的对象,而一个对象可以在不同时间具有不同的值,但它始终是同一个对象。与对象类似,表具有独立于创建者或创建位置的生命周期。
对象有自己的操作。表也可以有操作
Account = {balance = 0} function Account.withdraw (v) Account.balance = Account.balance - v end此定义创建一个新函数,并将其存储在
Account
对象的 withdraw
字段中。然后,我们可以像这样调用它
Account.withdraw(100.00)
这种函数几乎是我们所说的“方法”。但是,在函数中使用全局名称 Account
是一种不好的编程习惯。首先,此函数仅适用于此特定对象。其次,即使对于此特定对象,函数也仅在对象存储在该特定全局变量中时才有效;如果我们更改此对象的名称,withdraw
将不再起作用
a = Account; Account = nil a.withdraw(100.00) -- ERROR!这种行为违反了对象具有独立生命周期的前述原则。
一种更灵活的方法是对操作的“接收者”进行操作。为此,我们必须为方法定义一个额外的参数,该参数告诉方法它必须在哪个对象上进行操作。此参数通常具有名称 self 或 this
function Account.withdraw (self, v) self.balance = self.balance - v end现在,当我们调用方法时,我们必须指定它必须在哪个对象上进行操作
a1 = Account; Account = nil ... a1.withdraw(a1, 100.00) -- OK通过使用 self 参数,我们可以对多个对象使用相同的方法
a2 = {balance=0, withdraw = Account.withdraw} ... a2.withdraw(a2, 260.00)
在任何面向对象语言中,使用self 参数都是一个中心点。大多数面向对象语言都将这种机制部分地隐藏在程序员的视线之外,这样程序员就不必声明这个参数(尽管她仍然可以在方法内部使用名称self 或this)。Lua 也可以使用冒号运算符来隐藏这个参数。我们可以将前面的方法定义重写为
function Account:withdraw (v) self.balance = self.balance - v end并将方法调用重写为
a:withdraw(100.00)冒号的作用是在方法定义中添加一个额外的隐藏参数,并在方法调用中添加一个额外的参数。冒号只是一个语法工具,尽管它很方便;这里实际上没有什么新东西。我们可以使用点语法定义一个函数,并使用冒号语法调用它,反之亦然,只要我们正确处理额外的参数即可
Account = { balance=0, withdraw = function (self, v) self.balance = self.balance - v end } function Account:deposit (v) self.balance = self.balance + v end Account.deposit(Account, 200.00) Account:withdraw(100.00)
现在我们的对象有了标识、状态和针对此状态的操作。它们仍然缺少类系统、继承和私有性。让我们解决第一个问题:如何创建具有类似行为的多个对象?具体来说,我们如何创建多个帐户?
版权所有 © 2003–2004 Roberto Ierusalimschy。保留所有权利。 |