Skip to main content

Classes

Lua doesn't offer directly a class structure like every OOP languages like PHP and Java. Because of that, there are a couple of ways we can emulate classes and effectively be able to instantiate objects that share logic, property, methods structure, etc.

The Stormwind Library proposes a few standards to achieve class structures that are created with a couple of metatables settings and some indentation.

Class standards

These are the standards used by Stormwind Library for a table to be considered a class:

  • Each class is defined in its own file, which is later merged to the single library file
  • All lines below the first local declaration are indented as they belong to an opened structure
  • Classes have a constructor similar to PHP's, called __construct()
  • Due to how the library is compiled, when this "class" is being read by the Lua compiler, the self calls are actually referencing the Library instance, not the class being written -- only the self's inside methods refer to the "class" itself, and because of that, a self:addClass() is called at the top, so the library can store a reference for this "class", declared as local. After that, the library can instantiate that class anywhere in the addon code.
    • If the point above is a bit confusing, read the factory documentation for more information and examples
"Private" constructors

Sometimes it's recommended not to expose classes structures for free instantiation. When that happens, simply don't call self:addClass(), so library:new() won't have any effects on it, behaving as a private constructor, when only the classes themselves can create their own instances.

As an example, the raid marker model has a limited number of possible instances. That class can't be instantiated by any addons and its instances are generated by the library during its initialization.

Abstract methods

Abstract methods can be mimicked by creating a method that throws an error when called. This way, the developer is forced to implement that method in a child class. Example:

function AbstractClass:doSomething()
error('This is an abstract method and should be implemented by this class inheritances')
end

See how you can register an abstract class here.

Class recipe

Use the recipe below to create new classes.

This is an example of a simple class with no properties.

--[[--
Class description.

@classmod Module.ClassName
]]
local ClassName = {}
ClassName.__index = ClassName
ClassName.__ = self
self:addClass('ClassName', ClassName)

--[[--
ClassName constructor.
]]
function ClassName.__construct()
local self = setmetatable({}, ClassName)

-- add properties here

return self
end
-- end of ClassName

And this is an example of the first test class version for the class above:

TestClassName = BaseTestClass:new()

-- @covers ClassName:__construct()
TestCase.new()
:setName('__construct')
:setTestClass(TestClassName)
:setExecution(function()
local instance = __:new('ClassName', --[[ args here ]])
lu.assertNotNil(instance)
end)
:register()
-- end of TestClassName

Models

Please, refer to the models documentation for more information on how to create models following the Stormwind Library standards.