Objects Without a Class Keyword
Lua has no built-in class keyword. Instead, objects are ordinary tables that hold both data (fields) and behavior (functions stored as fields). A "method" is simply a table entry whose value happens to be a function, and "object-oriented" style in Lua is really just a convention for organizing tables and using the colon : syntax to pass the table itself as an implicit first argument, traditionally named self.
Cricket analogy: A batter's stats table in a scoring app is just a table with runs, balls, and a strikeRate() function attached to it, the same way Virat Kohli's profile bundles data and calculated behavior together rather than needing a separate 'BatterClass' definition.
-- A simple object as a table
local dog = {}
dog.name = "Rex"
dog.sound = "Woof"
function dog.speak(self)
print(self.name .. " says " .. self.sound)
end
dog.speak(dog) -- explicit self
dog:speak() -- colon sugar, identical resultThe Colon Operator and self
The colon obj:method(args) is syntactic sugar for obj.method(obj, args). When you define a function with function obj:method(args) ... end, Lua automatically inserts self as the first parameter. This convention lets a single function definition work for any table that shares the same shape, because self refers to whichever table is on the left of the colon at call time, not a fixed object baked into the function.
Cricket analogy: When a commentator says 'Rohit Sharma plays a cover drive,' the shot technique is the same function applied with Rohit as the implicit subject, just as player:cover_drive() inserts whichever player table is self.
Constructors and Encapsulation
There is no new keyword; instead, programmers write a plain function (often called Dog.new() or via Dog.__index = Dog) that creates a fresh table, sets its fields, and returns it. Encapsulation is achieved by convention rather than enforcement: fields prefixed with an underscore, or values stored in a closure rather than the table itself, signal "private" data, since Lua has no private or public access modifiers.
Cricket analogy: A scorer manually filling in a fresh scorecard for every new match, rather than the stadium providing a pre-built 'MatchClass', mirrors how Lua's Dog.new() builds a table from scratch each time.
By convention, Lua OOP libraries name the table that holds shared methods after the "class" itself (e.g. Dog), and instances are separate tables whose metatable's __index points back to Dog. This pattern is covered in depth in the next topic, Inheritance with Metatables.
Why Convention Instead of Enforcement
Because Lua is a minimal, embeddable language, its designers chose not to bake in OOP mechanics, leaving library authors free to implement classes, prototypes, mixins, or purely functional styles as needed. This is why frameworks like middleclass, classic.lua, and 30log exist purely as small Lua libraries built from tables and metatables, not language extensions, and why understanding raw tables and self is essential before using any of them.
Cricket analogy: The ICC lets each cricket board decide its own domestic tournament format rather than mandating one globally, just as Lua leaves OOP style up to library authors instead of enforcing one class system.
- Lua has no built-in class keyword; objects are ordinary tables holding data fields and function-valued methods.
- The colon syntax
obj:method(args)is sugar forobj.method(obj, args), automatically passing the table asself. - Constructors are plain functions (commonly named
.new()) that build and return a fresh table, sincenewis not a reserved word. - Encapsulation is convention-based; Lua has no
private/publicmodifiers, so underscore-prefixed names or closures signal restricted access. - Popular OOP libraries like middleclass and classic.lua are implemented entirely in Lua using tables and metatables, not language features.
- Understanding raw tables and how
selfbinds at call time is a prerequisite for using metatable-based inheritance.
Practice what you learned
1. What does `dog:speak()` desugar to in Lua?
2. Which statement about Lua's object system is correct?
3. In `function Dog:bark() print(self.name) end`, what does `self` refer to?
4. Why doesn't Lua have a built-in class system?
Was this page helpful?
You May Also Like
Inheritance with Metatables
Understand how Lua uses metatables and the __index metamethod to implement inheritance chains between tables.
Modules and require
Learn how Lua organizes reusable code into modules with the require function, package.path, and the standard return-a-table pattern.
Error Handling in Lua (pcall/error)
Learn how Lua signals and catches errors using error(), pcall(), and xpcall(), instead of try/catch exceptions.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics