programming in lua, objects
As others have said, self
(the Account
table) is used as a metatable assigned to the objects created using new
. Simplifying slightly (more info available at the links provided) when a field is not found in 'o', it goes to the 'Account' table because o's metatable says to go to Account (this is what __index
does).
It does not, however, need to be executed every time an object is created. You could just as easily stick this somewhere:
Account.__index = Account
and it would work as well.
The somewhat longer story is that if an object o
has a metatable, and that metatable has the __index
field set, then a failed field lookup on o
will use __index
to find the field (__index
can be a table or function). If o
has the field set, you do not go to its metatable's __index
function to get the information. Again, though, I encourage you to read more at the links provided above.
The Lua documentation is somewhat vague on this detail and many of the answers here either echo the Lua docs or don't thoroughly explain this confusing tidbit.
The line self._index = self
is present purely for the benefit of the newly-created object, o
; it has no meaningful or functional impact on Account
.
The _index
field only has special meaning within the context of metatables; therefore self._index
is just a plain old regular field for Account
. However, when Account
is used as a metatable for o
, the _index
field "becomes" a metamethod for o
. (So what's a field for Account
is a metamethod for o
.)
When you take the two statements in combination ...
(1) setmetatable(o, self) (2) self._index = self
... you're using Account
as the metatable for o
on line (1) and setting the _index
metamethod for o
to Account
on line (2). (On line (2), you're also setting the "plain old field" __index
in Account
to Account
.) So the useful aspect of self._index = self
isn't the setting of the _index
field for Account
, but rather the setting of the _index
metamethod for o
.
The following is functionally equivalent:
setmetatable(o, self) getmetatable(o)._index = self
Lua is not an object-oriented language, but it has all of the facilities for writing object-oriented code. However, it is done in a prototyping fashion a la JavaScript. Instead of explicitly creating classes, a prototype object is created and then cloned to create new instances.
The __index
metamethod is invoked to perform key lookups on read accesses to a table when the key is not already present in the table. So, self.__index = self
essentially allows for inheritance of all methods and fields of the Account
"class" by the new "instance" that is created in the o = o or {}
and setmetatable(o, self)
lines.
See also:
- Metatables
- Metamethods Tutorial
- Inheritance Tutorial