Lua Class Factories
A class factory is a function that builds and returns a new class from a spec table.
A factory builds a class from a spec table
The factory takes a spec with a kind and a starting balance. It returns a class, and an object from that class reports those spec values.
local function makeAccountClass(spec)
local Class = {}
Class.__index = Class
Class.kind = spec.kind
function Class.new()
local self = setmetatable({}, Class)
self.balance = spec.start
return self
end
function Class:report()
return self.kind .. " balance " .. self.balance
end
return Class
end
local Savings = makeAccountClass({kind = "Savings", start = 100})
local a = Savings.new()
print(a:report())One factory can build two different kinds
The same factory builds Savings and Checking from different spec tables. Each class reports its own kind and starting balance.
local function makeAccountClass(spec)
local Class = {}
Class.__index = Class
Class.kind = spec.kind
function Class.new()
local self = setmetatable({}, Class)
self.balance = spec.start
return self
end
function Class:report()
return self.kind .. " balance " .. self.balance
end
return Class
end
local Savings = makeAccountClass({kind = "Savings", start = 100})
local Checking = makeAccountClass({kind = "Checking", start = 50})
local a = Savings.new()
local b = Checking.new()
print(a:report())
print(b:report())Factory objects still keep their own state
Two savings objects start at the same balance. A deposit on the first object leaves the second object unchanged.
local function makeAccountClass(spec)
local Class = {}
Class.__index = Class
Class.kind = spec.kind
function Class.new()
local self = setmetatable({}, Class)
self.balance = spec.start
return self
end
function Class:deposit(amount)
self.balance = self.balance + amount
end
function Class:report()
return self.kind .. " balance " .. self.balance
end
return Class
end
local Savings = makeAccountClass({kind = "Savings", start = 100})
local a = Savings.new()
local b = Savings.new()
a:deposit(25)
print(a:report())
print(b:report())Example
local function makeAccountClass(spec)
local Class = {}
Class.__index = Class
Class.kind = spec.kind
function Class.new()
local self = setmetatable({}, Class)
self.balance = spec.start
return self
end
function Class:deposit(amount)
self.balance = self.balance + amount
end
function Class:withdraw(amount)
if amount <= self.balance then
self.balance = self.balance - amount
end
end
function Class:report()
return self.kind .. " balance " .. self.balance
end
return Class
end
local Savings = makeAccountClass({kind = "Savings", start = 200})
local Checking = makeAccountClass({kind = "Checking", start = 80})
local a = Savings.new()
local b = Checking.new()
a:deposit(50)
b:withdraw(30)
print(a:report())
print(b:report())Key points
- Spec table: A spec table is a plain table that lists the settings for one kind, such as a kind name and a starting balance.
- Factory function: A factory function takes a spec table and returns a class built from its settings.
- Shared code: All classes from one factory share the same method code, but each class uses its own spec values.
- Kind field: Each class can store its kind from the spec, so objects can report which kind they are.
- Own state: Objects made from a factory class still keep their own fields, just like objects from a hand-written class.
In this example, the factory builds a class from a spec table, with deposit, withdraw, and report methods. Savings and Checking are built from different spec tables. A savings object gains fifty, and a checking object loses thirty, so the reports show two hundred fifty and fifty.
Note
The factory returns the class table itself, not an object, so you still call new on the returned class to make objects.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
What does a class factory return?