Getting Started

Last Updated: 2009-01-31 for 1.0.0

Getting Started with LibOOP

LibOOP is framework-independent; its only dependency is LibStub, so you'll start by getting a handle for the library. For alpha builds, you'll need:
local liboop = LibStub("LibOOP-1.0-alpha")
while beta and release builds will be available as:
local liboop = LibStub("LibOOP-1.0")
This separation ensures that your addon or library can embed a stable version of LibOOP, and not worry about some other addon replacing it with a potentially unstable alpha build. If you want the latest version no matter what, you can use something like:
local liboop = LibStub("LibOOP-1.0-alpha",true) or LibStub("LibOOP-1.0")

Classes

You can define a new class like so:
local MyClass = liboop:Class()
This gives you a table whose metamethods have been set up such that it functions as a class.

The Base Class

Natively object-oriented languages usually provide a number of operators, keywords and built-in language functions to facilitate object-oriented design. Since LibOOP cannot modify the Lua language, it instead provides these features through methods. Every LibOOP class inherits from an invisible "base class" which provides the methods GetSuperClass, Extend, New, SubClassOf and Super. The base class also provides a "base prototype," from which all LibOOP objects inherit the methods Clone, GetClass, InstanceOf and Super.

Class Methods

Class methods are defined in the "normal" Lua way:
function MyClass:MyMethod(arg1, arg2) ... end
Since a LibOOP class is just a table, the normal table rules apply: you cannot have a method and a property of the same name, and you can overwrite previous definitions at any time. However, some methods which are inherited from the base class cannot be redefined; see the section on Overriding Methods for details.

Objects

Like classes, LibOOP objects are tables whose metamethods have been set up such that they function as objects. To create an object (that is, to instantiate a class), use the New method of the class:
local obj1 = MyClass:New()
or, call the class like a function:
local obj1 = MyClass()
The default constructor does not take any arguments. To customize your class constructor, see the section on Overriding Methods.

Instance Methods

Class instances (objects) inherit their methods from their class' "prototype," which is a property of the same name that LibOOP provides on the class' table. So, to define an instance method (as opposed to a class method), just define it on the class' prototype subtable (instead of the class itself):
function MyClass.prototype:MyObjMethod(arg) ... end

Subclasses

To define a subclass, use the Extend method of the parent class:
local MySubClass = MyClass:Extend()
This new class functions exactly like our previous class, except it inherits all of its superclass' methods, including prototype methods. So we can immediately do:
MySubClass:MyMethod("foo","bar")
local subobj1 = MySubClass()
subobj1:MyObjMethod("baz")

Overriding Methods

To override an inherited method, just define it again on the subclass or subclass' prototype:
function MySubClass:New(name,number)
   local o = self:Super('New')
   o.name = name
   o.number = number
   return o
end
function MySubClass.prototype:MyObjMethod() ... end
Notice that we overrode the New method of our class; this is the way to implement a constructor, and will now function like so:
local subobj2 = MySubClass("bob",42)
This example also demonstrates the use of Super, which is how an overriding method definition can call the inherited version of the method that it is overriding. It is also allowed to override the Extend method of classes and Clone of instances; it is not allowed to override any other methods inherited from the base class or base prototype. For details on how to override these methods, see the API pages.

Additional Notes

Inheritance Implementation

LibOOP handles inheritance with __index metamethods on classes and objects. Specifically, classes index their superclass, objects index their class' prototype, and prototypes index their superclass' prototype. This arrangement has some pros and cons. On the one hand, it preserves the fully dynamic nature of Lua -- if you add a new method to a class or prototype, any subclasses, objects or subclass objects will immediately have access to it (unless they already define it). On the other hand, these __index lookups take some time, so there is a performance penalty when calling methods, especially if they're been inherited along a very long class chain.

Scope

LibOOP does not provide anything akin to the inheritance scope seen in other languages (i.e. public/protected/private). All methods and properties are effectively public. However, you can simulate private properties by using local variables in closure in the file that defines your class. For example:
local class_nextID = 1
local object_id = {}

function MyClass.prototype:__init()
  object_id[self] = class_nextID
  class_nextID = class_nextID + 1
end

function MyClass.prototype:GetID()
  return object_id[self]
end
If you do this, it is strongly recommended that you make any such tables "weak", so that they do not interfere with garbage collection:
setmetatable(object_id, {__mode='k'})
Last Updated: 2009-01-31 for 1.0.0

Comments

Posts Quoted:
Reply
Clear All Quotes