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
endThe 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
EasyLet'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:
- The owner's name
- The initial balance (a number)
- 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: 650Remember: 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
endThis 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}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1The 'Self' Concept
Tables with FunctionsExplicit 'self'The Colon SyntaxDot vs ColonRecap - Moving Point4Project: Digital Bank
Project SetupDeposit Method7Polymorphism & Overriding
Overriding MethodsCalling Parent MethodsDuck TypingCommon InterfaceChecking TypeRecap - Employee Roles10Project: Shape Manager
Project SetupRectangle Class2Class Prototype Pattern
The Prototype ConceptLinking with __indexThe :new() ConstructorInitializing AttributesIndependent InstancesRecap - Car Factory5Operator Overloading in OOP
Adding ObjectsSubtracting ObjectsConcatenating ObjectsComparing Objects (<, >)Recap - Wallet Math8Encapsulation
Naming ConventionsClosures for PrivacyAccess via ClosuresRead-Only TablesValidation LogicRecap - Secure Vault11Design Patterns (Lite)
Factory FunctionsSingleton TableIterator PatternObserver (Listener)Recap - Logger Factory3Object State and Behavior
Instance VariablesGetter MethodsSetter MethodsCalculated PropertiesFormatting StringsEquality ChecksRecap - Student Grade6Inheritance Basics
The Inheritance SetupInheriting MethodsExtending the ConstructorAdding Child MethodsShared vs UniqueRecap - Shape Hierarchy