第一版是为 Lua 5.0 编写的。虽然在很大程度上仍然适用于后续版本,但有一些差异。
第四版针对 Lua 5.3,可在 亚马逊 和其他书店购买。
购买本书,您还可以帮助支持 Lua 项目。
![]() |
用 Lua 编程 | ![]() |
| 第二部分。表和对象 第 16 章。面向对象编程 |
由于类是对象,因此它们也可以从其他类获取方法。这使得在 Lua 中实现继承(以通常的面向对象含义)变得非常容易。
让我们假设我们有一个基类,如 Account
Account = {balance = 0}
function Account:new (o)
o = o or {}
setmetatable(o, self)
self.__index = self
return o
end
function Account:deposit (v)
self.balance = self.balance + v
end
function Account:withdraw (v)
if v > self.balance then error"insufficient funds" end
self.balance = self.balance - v
end
从该类中,我们希望派生出一个子类 SpecialAccount,该子类允许客户提取超过其余额的金额。我们从一个空类开始,该类仅从其基类继承所有操作
SpecialAccount = Account:new()到目前为止,
SpecialAccount 只是一个 Account 实例。现在发生了好事
s = SpecialAccount:new{limit=1000.00}
SpecialAccount 从 Account 继承 new,就像任何其他方法一样。然而,这次当 new 执行时,self 参数将引用 SpecialAccount。因此,s 的元表将是 SpecialAccount,其在索引 __index 处的值为 SpecialAccount。因此,s 从 SpecialAccount 继承,而 SpecialAccount 从 Account 继承。当我们评估
s:deposit(100.00)Lua 无法在
s 中找到 deposit 字段,因此它会查找 SpecialAccount;它也无法在其中找到 deposit 字段,因此它会查找 Account,并在其中找到存款的原始实现。
让 SpecialAccount 变得特别的是,它可以重新定义从其超类继承的任何方法。我们所要做的就是编写新方法
function SpecialAccount:withdraw (v)
if v - self.balance >= self:getLimit() then
error"insufficient funds"
end
self.balance = self.balance - v
end
function SpecialAccount:getLimit ()
return self.limit or 0
end
现在,当我们调用 s:withdraw(200.00) 时,Lua 不会转到 Account,因为它首先在 SpecialAccount 中找到了新的 withdraw 方法。因为 s.limit 是 1000.00(请记住,我们在创建 s 时设置了此字段),所以程序执行了取款操作,使 s 余额为负。
Lua 中面向对象编程的一个有趣方面是,您无需创建新类来指定新行为。如果只有一个对象需要特定行为,则可以直接在对象中实现该行为。例如,如果帐户 s 表示某个特殊客户,其限额始终为其余额的 10%,则您只能修改此单个帐户
function s:getLimit ()
return self.balance * 0.10
end
在该声明之后,调用 s:withdraw(200.00) 将运行 SpecialAccount 中的 withdraw 方法,但当该方法调用 self:getLimit 时,它将调用此最后定义。
| 版权所有 © 2003–2004 Roberto Ierusalimschy。保留所有权利。 | ![]() |