Trick Lua into becoming an object-oriented language

Lua isn't an object-oriented programming language. Here's a hack to use a Lua table as a stand-in for an object-oriented class.
No readers like this yet.
Woman sitting in front of her laptop

kris krüg

Lua isn't an object-oriented programming language, but a scripting language utilizing C functions and a C-like syntax. However, there's a cool hack you can use within Lua code to make Lua act like an object-oriented language when you need it to be. The key is in the Lua table construct, and this article demonstrates how to use a Lua table as a stand-in for an object-oriented class.

What is object-oriented programming?

The term "object-oriented" is a fancy way of describing, essentially, a templating system. Imagine you're programming an application to help users spot and log zombies during a zombie apocalypse. You're using an object-oriented language like C++, Java, or Python. You need to create code objects that represent different types of zombies so the user can drag them around and arrange them on a map of the city. Of course a zombie can be any number of things: dormant, slow, fast, hungry, ravenous, and so on. That's just textual data, which computers are good at tracking, and based on that data you could even assign the virtual "object" a graphic so your user can identify which general type of zombie each widget represents.

You have a few options for how you can resolve this requirement for your application:

  • Force your users to learn how to code so they can program their own zombies into your application

  • Spend the rest of your life programming every possible type of zombie into your application

  • Use a code template to define the attributes of a zombie object, allowing your users to create just the items they need, based on what zombie they've actually spotted

Obviously, the only realistic option is the final one, and it's done with a programming construct called a class. Here's what a class might look like (this example happens to be Java code, but the concept is the same across all object-oriented languages):

public class Zombie {
  int height;
  int weight;
  String speed;
  String location;
}

Whether or not you understand the code, you can probably tell that this is essentially a template. It's declaring that when a virtual "object" is created to represent a zombie, the programming language assigns that object four attributes (two integers representing height and weight, and two words representing the movement speed and physical location). When the user clicks the (imaginary) Add item button in the (imaginary) application, this class is used as a template (in programming, they say "a new instance" of the class has been created) to assign values entered by the user. Infinite zombies for the price of just one class. That's one of the powers of object-oriented programming.

Lua tables

In Lua, the table is a data type that implements an associative array. You can think of a table in Lua as a database. It's a store of indexed information that you can recall by using a special syntax. Here's a very simple example:

example = {}

example.greeting = "hello"
example.space = " "
example.subject = "world"

print(example.greeting ..
  example.space ..
  example.subject)

Run the example code to see the results:

$ lua ./example.lua
hello world

As you can tell from the sample code, a table is essentially a bunch of keys and values kept within a single collection (a "table").

Lua metatable

A metatable is a table that serves as a template for a table. You can designate any table as a metatable, and then treat it much as you would a class in any other language.

Here's a metatable to define a zombie:

Zombie = {}

function Zombie.init(h,w,s,l)
  local self = setmetatable({}, Zombie)
  self.height = h
  self.weight = w
  self.speed = s
  self.location = l
  return self
end

-- use the metatable

function setup()
  z1 = Zombie.init(176,50,'slow','Forbes & Murray Avenue')
end

function run()
  print(z1.location .. ": " ..
  z1.height .. " cm, " .. z1.weight .. " kg, " .. z1.speed)
end

setup()
run()

To differentiate my metatable from a normal table, I capitalize the first letter of its name. That's not required, but I find it a useful convention.

Here's the results of the sample code:

$ lua ./zombie.lua
Forbes & Murray Avenue: 176 cm, 50 kg, slow

This demonstration doesn't entirely do metatables justice, because the sample code creates just a single object with no interaction from the user. To use a metatable to satisfy the issue of creating infinite items from just one metatable, you would instead code a user input function (using Lua's io.read() function) asking the user to provide the details of the zombie they spotted. You'd probably even code a user interface with a "New sighting" button, or something like that. That's beyond the scope of this article, though, and would only complicate the example code.

Creating a metatable

The important thing to remember is that to create a metatable, you use this syntax:

Example = {}

function Example.init(args)
  local self = setmetatable({}, Example)
  self.key = value
  return self
end

Using a metatable

To use a metatable once it's been created, use this syntax:

my_instance = Example.init("required args")

Object-oriented Lua

Lua isn't object-oriented, but its table mechanism makes handling and tracking and sorting data as simple as it possibly can be. It's no exaggeration to say that once you're comfortable with tables in Lua, you can be confident that you know at least half of the language. You can use tables (and, by extension, metatables) as arrays, maps, convenient variable organization, close-enough classes, and more.

Seth Kenlon
Seth Kenlon is a UNIX geek, free culture advocate, independent multimedia artist, and D&D nerd. He has worked in the film and computing industry, often at the same time.

Comments are closed.

Creative Commons LicenseThis work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.