Contributed by Marcelo da Silva Gomes
Lua is a simple procedural language, with only one data structure called Table (a set of key/value pairs). Keys and values can store any value, including functions. This data structure is flexible enough to be used as an array, a dictionary/hash/map or... an object!
Objects in Lua are just tables containing keys associated with strings, numbers, etc (attributes) and keys associataed with functions (methods). Attributes can be defined and accesed with '.' and methods with ':' (this is a sintactic sugar to create a function with an implicit self argument)
Inheritance can be implemented using the concept of metatables, that act like superclasses, and the setmetatable() function. The __index key stores the metatable of the table.
When a "method" is called, Lua searches for it in the table. If nothing is found, the search continues in the metatables.
-- Shape Shape = {} function Shape:new(newX, newY) local newShape = {x = newX, y = newY} setmetatable(newShape, {__index = Shape}) return newShape end function Shape:moveTo(newX, newY) self.x = newX self.y = newY end function Shape:rMoveTo(deltaX, deltaY) self:moveTo(self.x + deltaX, self.y + deltaY) end function Shape:draw() end -- Rectangle Rectangle = {} setmetatable(Rectangle, {__index = Shape}) function Rectangle:new(newX, newY, newWidth, newHeight) local newRectangle = {x = newX, y = newY, width = newWidth, height = newHeight} setmetatable(newRectangle, {__index = Rectangle}) return newRectangle end function Rectangle:draw() print(string.format( "Drawing a Rectangle at:(%d,%d), width %d, height %d", self.x, self.y, self.width, self.height )) end -- Circle Circle = {} setmetatable(Circle, {__index = Shape}) function Circle:new(newX, newY, newRadius) local newCircle = {x = newX, y = newY, radius = newRadius} setmetatable(newCircle, {__index = Circle}) return newCircle end function Circle:draw() print(string.format( "Drawing a Circle at:(%d,%d), radius %d", self.x, self.y, self.radius )) end -- create a collection containing various shape instances shapes = {Rectangle:new(10, 20, 5, 6), Circle:new(15, 25, 8)} for i, shape in ipairs(shapes) do shape:draw() shape:rMoveTo(100, 100) shape:draw() end -- access a rectangle specific function rectangle = Rectangle:new(0, 0, 15, 15) rectangle.width = 30 rectangle:draw()
Drawing a Rectangle at:(10,20), width 5, height 6 Drawing a Rectangle at:(110,120), width 5, height 6 Drawing a Circle at:(15,25), radius 8 Drawing a Circle at:(115,125), radius 8 Drawing a Rectangle at:(0,0), width 30, height 15