28. Many objects together
Chapters 26 and 27 built one object at a time. Classes shine with many objects of one kind treated as a group: a party of characters, a swarm of enemies. This chapter combines two things you know — a class (Chapter 27) and a list (Chapter 22) — into the everyday pattern of a list of objects.
A class to make many of
A small Critter class — a constructor and two methods,
the Chapter 27 pattern.
local Critter = {}
Critter.__index = Critter
function Critter.new(name, energy)
local self = setmetatable({}, Critter)
self.name = name
self.energy = energy
return self
end
function Critter:play()
self.energy = self.energy - 1
print(self.name .. " plays. Energy: " .. self.energy)
end
function Critter:isTired()
return self.energy <= 0
endPut the objects in a list
Each Critter.new(...) returns a fresh instance. Store
several in a list, like any value:
local critters = {
Critter.new("Spark", 3),
Critter.new("Bolt", 2),
Critter.new("Nova", 1),
}critters is a normal list (Chapter 22). What's new is
that each item is an object with its own state and methods.
Loop and call a method on each
Walk the list with ipairs and call a method on each
object. Each acts on its own data:
for _, c in ipairs(critters) do
c:play()
endOutput:
Spark plays. Energy: 2
Bolt plays. Energy: 1
Nova plays. Energy: 0
One loop, three objects, three separate energies. This is the core move of object-oriented code: keep a collection, act on it as a group, and let each object track itself.
Open exercises/28/01-critters.lua. It builds a list of
critters and makes each play once. Add a second loop so each plays
again, and watch the energies drop.
Filtering and counting objects
Because it's just a list, every Chapter 20 loop pattern works on objects too. Count how many critters are tired:
local tired = 0
for _, c in ipairs(critters) do
if c:isTired() then
tired = tired + 1
end
end
print(tired .. " critters need a rest.") -- 1 critters need a rest.The if calls a method
(c:isTired()) instead of testing a plain field, but the
count pattern is unchanged.
Adding and removing objects
table.insert and table.remove (Chapter 24)
work on a list of objects just like a list of numbers:
table.insert(critters, Critter.new("Zip", 5)) -- a new critter joins
table.remove(critters, 1) -- the first one leavesObjects are values like any other — added, removed, sorted, and counted.
Homework
Homework files are in exercises/28/homework/.
Problem 1 — A party of heroes
Open exercises/28/homework/01-party.lua. A small
Hero class is provided. Create a list of three heroes with
different names and hit points, then loop over the list and print each
one's name and HP on its own line.
Problem 2 — Total HP
Open exercises/28/homework/02-total-hp.lua. Use the
accumulate pattern to add up everyone's HP and print the team total.
Problem 3 — Who is hurt?
Open exercises/28/homework/03-who-is-hurt.lua. Each hero
has an hp and a max_hp. Loop over the party
and print every hero whose hp is below
max_hp.
Challenge — Strongest hero
Open exercises/28/homework/04-strongest.lua. Loop over
the party and print the name of the hero with the most HP. Use the
accumulate-a-maximum idea: remember the best so far, replacing it when
you find a stronger one.
Stuck or finished? Open the homework solutions page.