Put Some OOP in Your App -- Part 1: Creating a Class
Friday, January 21, 2011 at 2:29 PM If you’re like me, when you started using Corona and programming in Lua, you dove in and got right to coding. Maybe you looked into object-oriented programming in Lua, but soon realized it doesn’t have anything built into the language for it. And maybe, like me, you were a little intimidated by all the different methods other people have come up with for OOP in Lua, so you just skipped it for now and said, “I’ll get back to it later when I have more time.”
If that describes you, and you still haven’t used OOP in your Lua/Corona projects, this article might help. I’ll show you that there’s a very easy way to approach object-oriented programming, which can do wonders for organizing your code as your projects grow larger, not to mention improving the potential for reusability.
As I mentioned before, there are lots of ways to do OOP in Lua, but the simplest way, described in PiL, is the one I’m going to illustrate here.
Let's start with a simple example. I'm going to create a Number class. All it's going to do is store a number, increment it, decrement it, and return its value.
Number = {}
Number.__index = Number
On line 1, we create an object called Number and assign it an empty table. In Lua OOP, objects and classes are interchangeable. A class is really just an object (table) that we decide to call a class.
On line 2, we set the __index() metamethod for Number to the Number table itself. You can click here to learn more about what the __index() function does, but I'll explain a little bit more in a bit.
This sets up the basic class, but there's more we need to do. The most important part now is to write a constructor that will create instances of the class:
function Number:new(i)
local o = {_i = i}
setmetatable(o, self)
return o
end
I call this function "new" because that's what PiL does, and it makes the most sense to me, but really you can call it whatever you like. If you'd rather create your objects using a function called createObject(), go for it. You should be familiar with the ":" calling notation by now, especially if you use Corona. If you're not, it's very simple. Calling o:func(a,b,c) is the same as calling o.func(o,a,b,c). And defining function o:func(a,b,c) is the same as function o.func(self,a,b,c) where "self" points to the object o.
The first line in the new() function creates the actual object "o". If there are values you want to initialize here, that's fine, but you can also just pass an empty {} here and set the values afterwards. The next line sets the metatable of the object to the metatable of the class. This is the key to inheritance.
OK so what's a metatable? It's a little complicated, but I'll try to keep it simple and to the
point for this tutorial. A metatable is a set of methods that are attached to a table. The names of these
"metamethods" are pre-defined by Lua, and always start with two underscores ("__"). You'll remember
we set
Whew! That was a lot of explanation. So setting the metatable for our new object means that whatever functions we define for the Number class, you can call those functions by pointing to the object instead of the class.
Finally, to finish the definition of new(), we simply return the object we just created.
Now let's define some utility functions for our new class:
function Number:value() return self._i end function Number:increment() self._i = self._i + 1 end function Number:decrement() self._i = self._i - 1 end function Number:test(title) print(title) print(self:value()) self:increment(); print(self:value()) self:increment(); print(self:value()) self:decrement(); print(self:value()) print() end
That's it for our definition of the Number class. Again, this isn't meant to be useful; just illustrative. Here's an example of how we might use this class:
local num
num = Number:new()
num:test("Number")
When we execute this, we get the following result:
Number 1 2 3 2
This is exactly what we expect. First it prints the initial value, then it calls increment() twice, followed by decrement() once. Looks great!
You may have noticed that within the Number class, I store the value in a table element called "_i". I use the underscore for reason. Lua lacks one very important feature of OOP: information hiding. If you've programmed in almost any object-oriented language, you'll be familiar with the idea of hiding internal variables from outside code, and creating "getters" and "setters" to interface with those variables. Lua does not have privacy. There are ways you can build it in, but they have drawbacks.
Do you need to be concerned about the privacy of your internal variables? I think so, yes. Your code is less likely to have bugs if you're careful about how you access your class variables. If you have a class that represents a bank account, you only want other code to take money out of the account by using a withdraw() function. You don't want to leave the account balance open to be modified by anyone at all.
So how do we achieve privacy in Lua? Other programmers probably have different methods, but what works for me is simply putting an underscore ("_") in front of each variable in the class. That reminds me that I'm not supposed to access those variables directly; and it also makes it easy to search my code to see if "._" appears anywhere.
This tutorial should give you enough to get started with OOP in Lua if you've never tried it before. In my next tutorial I'll extend this class with several subclasses to illustrate how inheritance works. Stay tuned!
For reference, here's the complete source code so far:
Number = {}
Number.__index = Number
function Number:new(i)
local o = {_i = i}
setmetatable(o, self)
return o
end
function Number:value()
return self._i
end
function Number:increment()
self._i = self._i + 1
end
function Number:decrement()
self._i = self._i - 1
end
function Number:test(title)
print(title)
print(self:value())
self:increment(); print(self:value())
self:increment(); print(self:value())
self:decrement(); print(self:value())
print()
end
local num
num = Number:new(1)
num:test("Number")
I hope you've enjoyed this tutorial. If you found it useful, please consider following me on Twitter and/or sharing it with someone. Thanks!

In
In this tutorial I'm going to create a very simple program that places 10 balls randomly on the screen and moves each ball slowly to the left until it reaches x=50, at which point we'll kill it.