🎓 A1Learner
🔍
0 of 52 lessons completed

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?