29. Inheritance in depth — Homework solutions
Solution .lua files:
exercises/29/homework/solutions/.
Problem 1 — Vehicle and Car
Problem. A Car that inherits
describe from Vehicle.
Worked solution.
local Vehicle = {}
Vehicle.__index = Vehicle
function Vehicle.new(name)
return setmetatable({ name = name }, Vehicle)
end
function Vehicle:describe()
print(self.name .. " is a vehicle.")
end
local Car = setmetatable({}, { __index = Vehicle })
Car.__index = Car
function Car.new(name)
return setmetatable(Vehicle.new(name), Car)
end
Car.new("Beetle"):describe() -- Beetle is a vehicle. (inherited)Problem 2 — Override
Problem. Car:describe() says "car"
instead of "vehicle".
Worked solution. Add to the classes above:
function Car:describe()
print(self.name .. " is a car.")
end
Vehicle.new("Cart"):describe() -- Cart is a vehicle.
Car.new("Beetle"):describe() -- Beetle is a car.A Vehicle finds the original; a Car finds
its own first.
Problem 3 — Extend the parent
Problem. Car:describe() runs the
parent's version, then adds a line.
Worked solution.
function Car:describe()
Vehicle.describe(self)
print(" It has four wheels.")
end
Car.new("Beetle"):describe()
-- Beetle is a vehicle.
-- It has four wheels.Common mistakes.
- Calling the parent with
self:describe()insidedescribecalls this same method again and loops forever. Use the dot form on the parent class:Vehicle.describe(self).
Challenge — Two children
Problem. Bird and Fish
both inherit Animal and override move.
Worked solution.
local Animal = {}
Animal.__index = Animal
function Animal.new(name)
return setmetatable({ name = name }, Animal)
end
function Animal:move()
print(self.name .. " moves.")
end
local function child() -- a tiny helper: a class inheriting Animal
local C = setmetatable({}, { __index = Animal })
C.__index = C
function C.new(name) return setmetatable(Animal.new(name), C) end
return C
end
local Bird = child()
function Bird:move() print(self.name .. " flies.") end
local Fish = child()
function Fish:move() print(self.name .. " swims.") end
local creatures = { Bird.new("Robin"), Fish.new("Nemo") }
for _, c in ipairs(creatures) do
c:move()
end
-- Robin flies.
-- Nemo swims.Putting the inherit-from-Animal setup in one helper keeps both
children short, and each still overrides move its own
way.
Done?
You can share behaviour with a base class and specialise it in children — inheriting, overriding, and extending. The last chapter of Part 6 — Designing a small class — asks how to make a class pleasant to use.