5

I do most of my programming in Python, and I use OOP practices for most of my projects. I recently started taking a look at the Love2D game library and engine. I managed to get some things configured, and then thought about making a GameObject class. But, what's this? Lua doesn't have classes! It has tables, and metatables, and other such things. I'm having a lot of trouble making heads or tails of this even after reading the documentation several times over.

Consider the following example:

catClass = {}
catClass.__index = catClass
catClass.type = "Cat"

function catClass.create(name)
    local obj = setmetatable({}, catClass)
    obj.name = name
    return obj
end

cat1 = catClass.create("Fluffy")
print(cat1.type)

cat2 = catClass.create("Meowth")

cat1.type = "Dog"

print(cat1.type)
print(cat2.type)
print(catClass.type)

The output of this is as follows:

Cat
Dog
Cat
Cat

What I do not understand is why changing cat1.type to "Dog" does not cause identical changes in cat2 and catClass. Does setting a metatable create a copy of the table? Google did not provide useful results (there are very few good Lua explanations).

2 Answers2

7

When you index a table and a key does not exist then Lua will look to see if a metatable exists for the table. If one does then it will use the __index key of that metamethod to re-index your key.

When you created cat1 it inherited the catClass metatable. Then when you indexed type it will see that cat1 does not have a table entry called type and thus looks to the metatable to find it.

Then you set type on cat1 to Dog, which only sets the table key of cat1 itself, not the metatable. That is why when you index cat1 again for type you get Dog and not Cat.

If you go to http://www.lua.org/ there is documentation and some older copies of the Programming in Lua, written by the authors of Lua itself.

Paige DePol
  • 1,121
  • 1
  • 9
  • 23
4

See the setmetatable documentation - the table returned is the table specified in the first argument.

This is a different table for each invocation of create (thanks to {}) and each new table is also distinct from the metatable used. No copy was made, but rather a new table was created which is then "linked"1 to the metatable.

Thus there are three different tables in the above - cat1 (with mt catClass), cat2 (also with mt catClass) and catClass itself. Altering cat1, as done, therefor has no effect on the other two tables.


1 See Lua Metatables Tutorial; the use of the __index presented in the metatable effectively emulates JavaScript's [prototype] resolution.

When you look up a table with a key, regardless of what the key is, and a value hasn't been assigned for that key .. Lua will look for an __index key in the table's metatable .. If __index contains a table, Lua will look up the key originally used in the table belonging to __index.

However, __index has no affect on assigning a new index to one of the tables - the particular table is just modified as normal. (The tutorial also goes on to explain __newindex, if such write-through behavior is desired.)

user2864740
  • 60,010
  • 15
  • 145
  • 220