{ |one, step, back| }

The Shape Example in Lua

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.

Code for Lua

File: shapes.lua

-- Shape
Shape = {}

function Shape:new(newX, newY)
    local newShape = {x = newX, y = newY}
    setmetatable(newShape, {__index = Shape})
    return newShape

function Shape:moveTo(newX, newY)
    self.x = newX
    self.y = newY

function Shape:rMoveTo(deltaX, deltaY)
    self:moveTo(self.x + deltaX, self.y + deltaY)

function Shape:draw()

-- 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

function Rectangle:draw()
        "Drawing a Rectangle at:(%d,%d), width %d, height %d", 
        self.x, self.y, self.width, self.height

-- 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

function Circle:draw()
        "Drawing a Circle at:(%d,%d), radius %d", 
        self.x, self.y, self.radius

-- 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:rMoveTo(100, 100)

-- access a rectangle specific function
rectangle = Rectangle:new(0, 0, 15, 15)
rectangle.width = 30


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