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

Tags:

Lua