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:
class()
method somewhere near the top of your script.local MyClass = class()
init
method that accepts your class creation parametersfunction MyClass:init(etc)
function MyClass:method_name(etc)
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
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
.
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!