Back to Blog

Lua with Neowin: OOP with Metatables — __index, :new(), Colon Syntax & Inheritance | Episode 30

Sandy LaneSandy Lane

Video: Lua with Neowin: OOP with Metatables — __index, :new(), Colon Syntax & Inheritance | Episode 30 by Taught by Celeste AI - AI Coding Coach

Watch full page →

Lua with Neowin: OOP with Metatables — __index, :new(), Colon Syntax & Inheritance

Lua does not have built-in classes, but you can implement object-oriented programming using metatables. This example demonstrates how to create a class-like table with a __index metamethod for method lookup, define a :new() constructor to create instances, use the colon syntax for methods with implicit self, and build inheritance chains where child classes extend and override parent behavior.

Code

-- Define the base class Animal
Animal = {}
Animal.__index = Animal  -- method lookup points to Animal table

-- Constructor for Animal
function Animal:new(name)
  local instance = setmetatable({}, self)  -- set Animal as metatable
  instance.name = name or "Unnamed"
  return instance
end

-- Method: speak
function Animal:speak()
  print(self.name .. " makes a sound.")
end

-- Method: describe
function Animal:describe()
  print("This is " .. self.name .. ", an animal.")
end

-- Define subclass Dog that inherits from Animal
Dog = setmetatable({}, {__index = Animal})
Dog.__index = Dog

-- Constructor for Dog
function Dog:new(name, breed)
  local instance = Animal.new(self, name)  -- call parent constructor
  instance.breed = breed or "Unknown"
  return instance
end

-- Override speak method
function Dog:speak()
  print(self.name .. " barks.")
end

-- New method specific to Dog
function Dog:fetch()
  print(self.name .. " is fetching the ball!")
end

-- Override describe method
function Dog:describe()
  print("This is " .. self.name .. ", a " .. self.breed .. " dog.")
end

-- Usage example
local animal = Animal:new("GenericAnimal")
animal:speak()       -- Output: GenericAnimal makes a sound.
animal:describe()    -- Output: This is GenericAnimal, an animal.

local dog = Dog:new("Fido", "Labrador")
dog:speak()          -- Output: Fido barks.
dog:fetch()          -- Output: Fido is fetching the ball!
dog:describe()       -- Output: This is Fido, a Labrador dog.

Key Points

  • Setting __index = self in a table allows method lookup to follow the prototype chain like a class.
  • The :new() method creates instances by setting the metatable of a new table to the class table.
  • The colon : syntax automatically passes the instance as the first argument self to methods.
  • Inheritance is achieved by chaining __index through parent tables, enabling method reuse and extension.
  • Child classes can override parent methods by defining their own versions, which Lua finds first during lookup.