JanetRossini.github.io

Lua, LSL, Blender, Python in Second Life


Project maintained by JanetRossini

Recipe: Defining a Class

May 30, 2025 • [designluaobjectsrecipetesting]


Using the Valkyrie Transport class() function, declaring a class is easier and less error-prone than directly setting up metatables and such. Here’s a quick recipe for using it.

You’ll need at least the class() function, which you can download using the button above. Put it somewhere near the beginning of your SLua file.

For even better results, consider using the combined framework, which includes our testing framework object Tests. This article concludes by showing the tests I wrote to give me confidence that the example actually works.

We’ll define a simple rectangle object as our example here. It will have just a few methods, enough to show you how to do what you need to do. We want to create rectangle objects. Each one will have an x coordinate, and y coordinate, signifying the lower left corner of the rectangle, and a width and height.

We want to be able to define a new Rectangle instance like this:

x, y = 10, 20
w, h = 15, 35
local rect = Rectangle(x, y, w, h)

We define the class with this:

local Rectangle = class()

As always, declaring things local speeds up the code substantially. With the simple call above, we have a new class named Rectangle. All the magical metatable stuff is done.

We provide for the initialization with this:

function Rectangle:init(x, y, w, h)
   self.x = x
   self.y = y
   self.width = w
   self.height = h
end

Now our class knows its values. We want two methods, one that gives us the x and y for the top right corner, and one that give us the rectangle area. We define the first one like this:

function Rectangle:top_right()
   return self.x + self.width, self.y + self.height
end

And the second like this:

function Rectangle:area()
   return self.width * self.height
end

That’s essentially all there is to it:

  1. Include the class() method somewhere near the top of your script.
  2. Define the class with
    local MyClass = class()
  3. Provide an init method that accepts your class creation parameters
    function MyClass:init(etc)
  4. Define methods with
    function MyClass:method_name(etc)

Completed Dish

Our complete class looks like this:

-- rectangle class

local Rectangle = class()
function Rectangle:init(x, y, w, h)
   self.x = x
   self.y = y
   self.width = w
   self.height = h
end

function Rectangle:top_right()
   return self.x + self.width, self.y + self.height
end

function Rectangle:area()
   return self.width * self.height
end

Caveat!

If you’re declaring your classes and objects local, and since local variables are almost four times faster to access than globals you probably should be, you’ll want to be sure to have things declared in the right order from top to bottom of the script. If Lua sees a variable name before it is declared, it assumes that it is global and when you later declare it, that fact will not be recognized. Your new uses, below that, will be local but the ones above will stay global. Chaos will ensue, mostly manifesting as accesses to nil.

Remarks: Testing

When I put code into my articles, I want to be sure that it really works. So for today’s article, I wrote a few tests, using our Tests framework, also available from the buttons above. Here are those tests, which give me confidence that my little example will actually work:

-- rectangle tests

function Tests:test_rectangle_exists()
   x, y = 10, 20
   w, h = 15, 35
   local rect = Rectangle(x, y, w, h)
   self:assert_equals(rect.x, 10)
   self:assert_equals(rect.y, 20)
   self:assert_equals(rect.width, 15)
   self:assert_equals(rect.height, 35)
end

function Tests:test_corner()
   x, y = 10, 20
   w, h = 15, 35
   local rect = Rectangle(x, y, w, h)
   local tx, ty = rect:top_right()
   self:assert_equals(tx, x + w)
   self:assert_equals(ty, y + h)
end

function Tests:test_area()
   x, y = 10, 20
   w, h = 15, 35
   local rect = Rectangle(x, y, w, h)
   self:assert_equals(rect:area(), w*h)
end

Defining classes is easy and less prone to mistakes using our free class() function. Questions are welcome in world or to valkyriejanet at gmail dot com.

Safe paths!