🎓 A1Learner
🔍
0 of 52 lessons completed

Lua Encapsulation with Closures

Encapsulation is a way to keep some state private inside an object while offering public methods to use it.

A private value is not a field on the object

The counter factory keeps count as a local value. The returned table offers add and get methods, but it has no count field.

local function newCounter()
  local count = 0
  local t = {}
  function t.add()
    count = count + 1
  end
  function t.get()
    return count
  end
  return t
end
local c = newCounter()
c.add()
c.add()
print(c.get())
print(c.count)

Each factory call makes fresh private state

Two counters come from the same factory. Adding to the first counter leaves the second counter at zero.

local function newCounter()
  local count = 0
  local t = {}
  function t.add()
    count = count + 1
  end
  function t.get()
    return count
  end
  return t
end
local a = newCounter()
local b = newCounter()
a.add()
a.add()
print(a.get())
print(b.get())

A public method controls changes to private state

The account factory keeps balance as a local value. Deposit is the only way to raise it in this program, and balance is not a field.

local function newAccount()
  local balance = 100
  local t = {}
  function t.deposit(amount)
    balance = balance + amount
  end
  function t.getBalance()
    return balance
  end
  return t
end
local a = newAccount()
a.deposit(50)
print(a.getBalance())
print(a.balance)

Example

local function newAccount(start)
  local balance = start
  local t = {}
  function t.deposit(amount)
    balance = balance + amount
  end
  function t.withdraw(amount)
    if amount <= balance then
      balance = balance - amount
    end
  end
  function t.balance()
    return balance
  end
  return t
end
local a = newAccount(100)
local b = newAccount(50)
a.deposit(25)
a.withdraw(40)
b.withdraw(10)
print(a.balance())
print(b.balance())

Key points

  • Private state: Private state is a local value inside a factory function that outside code cannot reach as a field.
  • Public method: A public method is a function in the returned table that outside code can call.
  • Factory function: A factory function returns a table of methods, and those methods keep using the factory locals after the factory returns.
  • Fresh state: Each call to the factory makes fresh locals, so two objects do not share private state.
  • Getter method: A getter method returns a private value without letting outside code change it as a field.

In this example, newAccount keeps balance as a local value and returns deposit, withdraw, and balance methods. Two accounts are made with different starting balances. The first account gains twenty-five and then loses forty, while the second account loses ten. The final balances are eighty-five and forty, and the balance value itself is never stored as a field on either account.

Note

Lua has no private keyword, so privacy comes from locals that are simply not placed in the returned table.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

Why does print(c.count) show nil for a counter made by the factory in this lesson?