Linking with __index
Part of the Object Oriented Programming section of Coddy's Lua journey — lesson 7 of 70.
You have a prototype table with properties and methods, but how do you make a new object actually use it? The answer lies in the __index metamethod.
When you access a key that doesn't exist in a table, Lua normally returns nil. However, if the table has a metatable with an __index field, Lua will look there instead. By setting __index to point at your prototype, any missing keys are automatically found in the prototype:
local Dog = {
species = "Canis familiaris",
legs = 4
}
function Dog:bark()
print("Woof!")
end
-- Create an empty instance
local myDog = {}
-- Link it to the prototype
setmetatable(myDog, { __index = Dog })
print(myDog.species) -- Output: Canis familiaris
myDog:bark() -- Output: Woof!The table myDog is completely empty, yet accessing myDog.species works. When Lua doesn't find species in myDog, it checks the metatable's __index and finds it in Dog.
This is the foundation of object-oriented programming in Lua. The instance can have its own unique data, while shared behavior lives in the prototype. In the next lesson, you'll learn how to wrap this pattern into a clean constructor function.
Challenge
EasyNow let's put the __index metamethod into practice! You'll create a prototype and link an instance to it, allowing the instance to access properties and methods it doesn't directly have.
You'll organize your code across two files:
Robot.lua: Define aRobotprototype table with:- A
modelfield set to"RX-100" - A
batteryLevelfield set to100 - A
:status()method that prints the robot's current state
- A
main.lua: Require the Robot module, then create an empty instance table and link it to the Robot prototype usingsetmetatablewith__index. This allows your empty instance to access everything from the prototype.
You will receive one input: a name to assign to your robot instance.
After linking the instance to the prototype:
- Assign the input name to your instance's
namefield (this becomes unique to the instance) - Call the
:status()method on your instance
Your :status() method should print in this exact format:
[name] ([model]) - Battery: [batteryLevel]%For example, if the input is Sparky, the output should be:
Sparky (RX-100) - Battery: 100%Notice how the instance has its own name, but accesses model and batteryLevel from the prototype through the __index link.
Cheat sheet
The __index metamethod allows objects to inherit properties and methods from a prototype table.
When you access a key that doesn't exist in a table, Lua checks if the table has a metatable with an __index field. If it does, Lua looks for the key in the table specified by __index.
To link an instance to a prototype:
local Prototype = {
property = "value"
}
function Prototype:method()
print("Method called")
end
-- Create an instance
local instance = {}
-- Link to prototype using __index
setmetatable(instance, { __index = Prototype })
-- Access prototype properties and methods
print(instance.property) -- Output: value
instance:method() -- Output: Method calledThe instance table can be empty, yet it can access all properties and methods from the prototype. The instance can also have its own unique properties that override or extend the prototype.
This pattern is the foundation of object-oriented programming in Lua, where instances share behavior from a prototype while maintaining their own unique data.
Try it yourself
-- Read input
local name = io.read()
-- Require the Robot module
local Robot = require('Robot')
-- TODO: Create an empty instance table
-- TODO: Link the instance to the Robot prototype using setmetatable with __index
-- TODO: Assign the input name to your instance's name field
-- TODO: Call the :status() method on your instance
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1The 'Self' Concept
Tables with FunctionsExplicit 'self'The Colon SyntaxDot vs ColonRecap - Moving Point4Project: Digital Bank
Project SetupDeposit Method7Polymorphism & Overriding
Overriding MethodsCalling Parent MethodsDuck TypingCommon InterfaceChecking TypeRecap - Employee Roles10Project: Shape Manager
Project SetupRectangle Class2Class Prototype Pattern
The Prototype ConceptLinking with __indexThe :new() ConstructorInitializing AttributesIndependent InstancesRecap - Car Factory5Operator Overloading in OOP
Adding ObjectsSubtracting ObjectsConcatenating ObjectsComparing Objects (<, >)Recap - Wallet Math8Encapsulation
Naming ConventionsClosures for PrivacyAccess via ClosuresRead-Only TablesValidation LogicRecap - Secure Vault11Design Patterns (Lite)
Factory FunctionsSingleton TableIterator PatternObserver (Listener)Recap - Logger Factory3Object State and Behavior
Instance VariablesGetter MethodsSetter MethodsCalculated PropertiesFormatting StringsEquality ChecksRecap - Student Grade6Inheritance Basics
The Inheritance SetupInheriting MethodsExtending the ConstructorAdding Child MethodsShared vs UniqueRecap - Shape Hierarchy