Courses/Lua/Metatables and Metamethods

    Metatables and Metamethods

    Unlock Lua's most powerful feature: customise how tables behave with operator overloading, default values, and OOP patterns.

    What You'll Learn

    • What metatables are and how setmetatable works
    • __index for default values and prototype chains
    • Operator overloading with __add, __sub, __eq, __tostring
    • Building OOP classes with metatables

    What Are Metatables?

    A metatable is a regular Lua table that defines special behaviours for another table. When Lua encounters an operation it doesn't know how to perform (like adding two tables), it checks the metatable for a metamethod โ€” a function that handles that operation.

    ๐ŸŽฎ Real-World Analogy: Think of a metatable like a user manual for a table. The table itself holds your data, but the manual (metatable) tells Lua what to do in special situations โ€” like "when someone asks for a key that doesn't exist, look it up here instead."

    local myTable = {}
    local myMeta = {}
    
    setmetatable(myTable, myMeta)   -- attach the metatable
    getmetatable(myTable)           -- returns myMeta

    Key Metamethods

    MetamethodTriggered When
    __indexAccessing a missing key
    __newindexSetting a new key
    __addThe + operator
    __subThe - operator
    __mulThe * operator
    __eqThe == operator
    __ltThe < operator
    __tostringtostring() or print()
    __callCalling table as function

    Metatables in Action

    See how __index, __add, and __newindex work.

    Try it Yourself ยป
    JavaScript
    // Lua Metatables โ€” simulated in JavaScript
    console.log("=== What Are Metatables? ===");
    console.log("Metatables let you customise how tables behave.");
    console.log("They intercept operations like +, -, [], tostring.");
    console.log();
    
    console.log("=== __index: Default Values ===");
    // Simulating __index metamethod
    const defaults = { color: "red", speed: 10, health: 100 };
    const player = new Proxy({name: "Hero", speed: 25}, {
      get(target, prop) {
        return prop in target ? target[prop] : defau
    ...

    OOP with Metatables

    Lua doesn't have a class keyword, but you can build a full OOP system using metatables. The pattern is elegant and used everywhere in Lua game development.

    -- Define a "class"
    local Animal = {}
    Animal.__index = Animal
    
    function Animal:new(name, sound)
      local instance = setmetatable({}, self)
      instance.name = name
      instance.sound = sound
      return instance
    end
    
    function Animal:speak()
      return self.name .. " says " .. self.sound .. "!"
    end
    
    -- Inheritance
    local Dog = setmetatable({}, {__index = Animal})
    Dog.__index = Dog
    
    function Dog:new(name)
      local instance = Animal.new(self, name, "Woof")
      instance.tricks = {}
      return instance
    end
    
    function Dog:learnTrick(trick)
      table.insert(self.tricks, trick)
    end
    
    -- Usage
    local rex = Dog:new("Rex")
    print(rex:speak())         -- "Rex says Woof!"
    rex:learnTrick("sit")

    โš ๏ธ Common Mistake

    Don't confuse . and : โ€” the colon (:) automatically passes self as the first argument. dog:speak() is equivalent to dog.speak(dog).

    OOP Pattern

    Build classes with inheritance using metatables.

    Try it Yourself ยป
    JavaScript
    // Lua OOP with Metatables โ€” simulated in JavaScript
    console.log("=== OOP Pattern in Lua ===");
    console.log("Lua has no 'class' keyword โ€” use metatables!");
    console.log();
    
    // Simulating Lua's OOP pattern
    class Animal {
      constructor(name, sound) {
        this.name = name;
        this.sound = sound;
      }
      speak() {
        return this.name + " says " + this.sound + "!";
      }
    }
    
    class Dog extends Animal {
      constructor(name) {
        super(name, "Woof");
        this.tricks = [];
      }
      learnTrick(trick) {
        this
    ...

    ๐Ÿ’ก Pro Tip

    The __index metamethod can be either a table (for prototype-style lookups) or a function (for computed/dynamic values). Using a function gives you full control over what happens when a missing key is accessed.

    ๐Ÿ“‹ Quick Reference

    ConceptSyntax
    Set metatablesetmetatable(t, mt)
    Get metatablegetmetatable(t)
    Default lookupmt.__index = fallback
    Method syntaxfunction T:method() end
    Constructorsetmetatable({}, {__index = T})

    ๐ŸŽ‰ Lesson Complete!

    You've mastered metatables โ€” Lua's secret weapon for OOP, operator overloading, and custom behaviours. In the final lesson, we'll apply everything to real game development with Lร–VE2D and Roblox!

    Sign up for free to track which lessons you've completed and get learning reminders.

    Previous

    Cookie & Privacy Settings

    We use cookies to improve your experience, analyze traffic, and show personalized ads. You can manage your preferences below.

    By clicking "Accept All", you consent to our use of cookies for analytics and personalized advertising. You can customize your preferences or reject non-essential cookies.

    Privacy Policy โ€ข Terms of Service