第一版是为 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。保留所有权利。 |