Calling Parent Methods
Part of the Object Oriented Programming section of Coddy's Lua journey — lesson 38 of 70.
Sometimes overriding a method completely isn't what you want. Instead, you might want to extend the parent's behavior—do what the parent does, then add something extra. To achieve this, you can call the parent method directly from within the child's override.
The technique uses dot syntax with the parent class name, explicitly passing self as the first argument:
local Animal = {}
Animal.__index = Animal
function Animal:new(name)
local obj = {name = name}
setmetatable(obj, Animal)
return obj
end
function Animal:speak()
print(self.name .. " makes a sound")
end
-- Dog extends the parent behavior
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})
function Dog:new(name)
local obj = Animal.new(Animal, name)
setmetatable(obj, Dog)
return obj
end
function Dog:speak()
Animal.speak(self) -- Call parent method first
print(self.name .. " wags tail happily")
endThe key line is Animal.speak(self). By using dot syntax on the parent class and passing self manually, we invoke the original method before adding our own behavior:
local buddy = Dog:new("Buddy")
buddy:speak()
-- Output:
-- Buddy makes a sound
-- Buddy wags tail happilyThis pattern is useful when the parent method does important work you don't want to duplicate. The child can run the parent's logic first, last, or even in the middle of its own code—giving you full control over how behaviors combine.
Challenge
EasyLet's build a greeting system where a FormalPerson extends the behavior of a regular Person! Instead of completely replacing how a person introduces themselves, the formal version will first do the standard introduction, then add an extra polite touch.
You'll organize your code across three files:
Person.lua: Your base class with a:new(name)constructor that stores the person's name. Include an:introduce()method that prints the person's name followed bysays hi. This is the base behavior that will be extended.FormalPerson.lua: A child class that inherits from Person. Its constructor should call the parent constructor to handle the name. Override the:introduce()method, but instead of replacing the parent's behavior entirely, call the parent's method first usingPerson.introduce(self), then print an additional line with the person's name followed bybows politely.main.lua: Require your FormalPerson module, read a name from input, create a FormalPerson instance, and call:introduce()to see both behaviors combined.
You will receive one input: the person's name.
When you call :introduce() on a FormalPerson, it should produce two lines of output—the first from the parent's method, the second from the child's addition:
{name} says hi
{name} bows politelyFor example, if the input is Eleanor, the output should be:
Eleanor says hi
Eleanor bows politelyThe key insight here is that FormalPerson doesn't duplicate the "says hi" logic—it delegates that work to the parent method, then adds its own unique behavior on top. This keeps your code clean and demonstrates how child classes can extend rather than replace parent functionality!
Cheat sheet
To extend a parent method's behavior instead of completely overriding it, call the parent method from within the child's override using dot syntax and explicitly passing self:
function ChildClass:method()
ParentClass.method(self) -- Call parent method
-- Add additional behavior
endComplete example showing method extension:
local Animal = {}
Animal.__index = Animal
function Animal:new(name)
local obj = {name = name}
setmetatable(obj, Animal)
return obj
end
function Animal:speak()
print(self.name .. " makes a sound")
end
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})
function Dog:new(name)
local obj = Animal.new(Animal, name)
setmetatable(obj, Dog)
return obj
end
function Dog:speak()
Animal.speak(self) -- Execute parent behavior first
print(self.name .. " wags tail happily") -- Add child behavior
end
local buddy = Dog:new("Buddy")
buddy:speak()
-- Output:
-- Buddy makes a sound
-- Buddy wags tail happilyThe parent method can be called at any point: before, after, or in the middle of the child's own logic, giving full control over how behaviors combine.
Try it yourself
-- main.lua: Entry point for the greeting system
local FormalPerson = require('FormalPerson')
-- Read the person's name from input
local name = io.read()
-- TODO: Create a FormalPerson instance with the given name
-- TODO: Call the introduce method on the FormalPerson 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