Menu
Coddy logo textTech

Naming Conventions

Part of the Object Oriented Programming section of Coddy's Lua journey — lesson 43 of 70.

In Lua, all table fields are publicly accessible by default. Anyone can read or modify self.health directly. While Lua doesn't enforce privacy, programmers use naming conventions to communicate intent—signaling which fields should be treated as internal implementation details.

The standard convention is to prefix private fields with an underscore:

local Player = {}
Player.__index = Player

function Player:new(name)
    local obj = {
        name = name,      -- Public: okay to access directly
        _health = 100,    -- Private: use methods instead
        _score = 0        -- Private: internal tracking
    }
    setmetatable(obj, Player)
    return obj
end

function Player:getHealth()
    return self._health
end

function Player:takeDamage(amount)
    self._health = self._health - amount
end

The underscore doesn't change how Lua works—player._health is still technically accessible. However, it serves as a clear warning to other programmers (and your future self): "This field is meant to be private. Access it through methods instead."

This convention matters because it separates the interface (what others should use) from the implementation (how it works internally). If you later need to add validation or change how health is stored, you only modify the methods—code using :getHealth() continues working unchanged.

challenge icon

Challenge

Easy

Let's build a BankAccount class that properly signals which fields are meant to be private using the underscore naming convention!

You'll organize your code across two files:

  • BankAccount.lua: Create a class that manages account information. The constructor :new(ownerName, initialBalance) should store the owner's name as a public field (owner) and the balance as a private field (_balance). Include three methods:
    • :getBalance() — returns the current balance
    • :deposit(amount) — adds the amount to _balance
    • :getOwner() — returns the owner's name
  • main.lua: Require your BankAccount module, read the owner's name, initial balance, and deposit amount from input. Create an account, make a deposit, then print the owner and final balance.

You will receive three inputs:

  1. The owner's name
  2. The initial balance (a number)
  3. The deposit amount (a number)

Your output should be two lines showing the owner and the final balance after the deposit:

Owner: {ownerName}
Balance: {finalBalance}

For example, if the inputs are Maria, 500, and 150, the output should be:

Owner: Maria
Balance: 650

Remember: the underscore prefix on _balance signals to other programmers that this field should be accessed through methods like :getBalance() and :deposit(), not directly. The owner field without an underscore indicates it's fine to access publicly.

Cheat sheet

In Lua, all table fields are publicly accessible by default. To communicate which fields should be treated as internal implementation details, use the underscore naming convention by prefixing private fields with an underscore (_).

The underscore doesn't enforce privacy—it's a signal to other programmers that the field should be accessed through methods instead of directly.

local Player = {}
Player.__index = Player

function Player:new(name)
    local obj = {
        name = name,      -- Public: okay to access directly
        _health = 100,    -- Private: use methods instead
        _score = 0        -- Private: internal tracking
    }
    setmetatable(obj, Player)
    return obj
end

function Player:getHealth()
    return self._health
end

function Player:takeDamage(amount)
    self._health = self._health - amount
end

This convention separates the interface (what others should use) from the implementation (how it works internally), making code more maintainable when changes are needed.

Try it yourself

-- Require the BankAccount module
local BankAccount = require('BankAccount')

-- Read inputs
local ownerName = io.read()
local initialBalance = tonumber(io.read())
local depositAmount = tonumber(io.read())

-- TODO: Create a new BankAccount with ownerName and initialBalance

-- TODO: Make a deposit using the depositAmount

-- TODO: Print the owner and final balance in the required format
-- Format:
-- Owner: {ownerName}
-- Balance: {finalBalance}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming