This first edition was written for Lua 5.0. While still largely relevant for later versions, there are some differences.
The fourth edition targets Lua 5.3 and is available at Amazon and other bookstores.
By buying the book, you also help to support the Lua project.
Programming in Lua | ||
Part II. Tables and Objects Chapter 16. Object-Oriented Programming |
Because classes are objects, they can get methods from other classes, too. That makes inheritance (in the usual object-oriented meaning) quite easy to implement in Lua.
Let us assume we have a base class like 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
From that class, we want to derive a subclass SpecialAccount
,
which allows the customer to withdraw more than his balance.
We start with an empty class
that simply inherits all its operations from its base class:
SpecialAccount = Account:new()Up to now,
SpecialAccount
is just an instance of Account
.
The nice thing happens now:
s = SpecialAccount:new{limit=1000.00}
SpecialAccount
inherits new
from Account
like any other method.
This time, however, when new
executes,
the self
parameter will refer to SpecialAccount
.
Therefore, the metatable of s
will be SpecialAccount
,
whose value at index __index
is also SpecialAccount
.
So, s
inherits from SpecialAccount
,
which inherits from Account
.
When we evaluate
s:deposit(100.00)Lua cannot find a
deposit
field in s
,
so it looks into SpecialAccount
;
it cannot find a deposit
field there, too,
so it looks into Account
and there it finds the original implementation for a deposit.
What makes a SpecialAccount
special is that it can redefine
any method inherited from its superclass.
All we have to do is to write the new method:
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 endNow, when we call
s:withdraw(200.00)
,
Lua does not go to Account
,
because it finds the new withdraw
method in SpecialAccount
first.
Because s.limit
is 1000.00
(remember that we set this field when we created s
),
the program does the withdrawal,
leaving s
with a negative balance.
An interesting aspect of OO in Lua is that you do not
need to create a new class to specify a new behavior.
If only a single object needs a specific behavior,
you can implement that directly in the object.
For instance, if the account s
represents some
special client whose limit is always 10% of her balance,
you can modify only this single account:
function s:getLimit () return self.balance * 0.10 endAfter that declaration, the call
s:withdraw(200.00)
runs the withdraw
method from SpecialAccount
,
but when that method calls self:getLimit
,
it is this last definition that it invokes.
Copyright © 2003–2004 Roberto Ierusalimschy. All rights reserved. |