Classes
Contents
What are classes?
Classes are simply a way to organize data to reflect an object. For example, you might have a player class that represents the player's object in the game world. That class would contain things such as health, position, status, and whatever else you can think of.
Classes can also use inheritance. Inheritance means that one object shares certain functionality with its "parent." If you were to make an object to represent a cat or dog, you might inherit behavior from the animal class.
Creating a new class
To create a new class, all you need to do is call class.new(). Calling that function with no parameters will return an empty class and will not call its constructor. If you call class.new() and pass it an object, it will return a new class that inherits behavior from that object.
Example:
Animal = class.new(); -- Make a new class, lets call it animal.
Cat = class.new(Animal); -- Make a new class called cat, which is a subclass of animal
Dog = class.new(Animal); -- Dogs are also a different subclass of animal, and may have different attributes than cats
Instantiation
Declaring a new class does not give immediately give you an object that you should use directly. Instead, think of it like a recipe: it tells you what the object contains, but it isn't ready to use.
In order to actually create an instance of a class, you need only to call its baseclass as a function, like so:
fluffy = Dog(); -- fluffy is now an object of type Dog
lucky = Dog(); -- lucky can be a different Dog
stripes = Cat(); -- And stripes can be a Cat
Constructors
Constructors are the functions that get called when creating an instance of a class. If we wanted our Dog to bark when we create one, we could do this:
function Dog:constructor()
print("Bark!");
end
fluffy = Dog(); -- This should now print "Bark!" on the screen.
A constructor can also take arguments. If, for some strange reason, you wanted to pass in the dog's age when creating it, you can do this:
function Dog:constructor(age)
print("Bark! I am age ", age);
end
fluffy = Dog(5); -- Should print: Bark! I am age 5
You may also wish to call its parent's constructor. You must be careful here. Do not call self.parent:constructor() directly, as doing so may cause an infinite loop and possibly a stack overflow. The proper way to do it is to specify the parent by calling <classname>.parent.constructor(self) instead.
Before Dog constructs itself, it might want to first initiate itself with some data:
function Animal:constructor()
self.type = "Animal";
end
function Dog:constructor()
Dog.parent.constructor(self);
print(self.type); -- This should print "Animal";
end
Variables & Functions
A class can contain any number of variables. It is recommended that class variables are declared in its constructor for clarity and for inheritance reasons. When calling from inside of a class, variables and functions, should be preceeded by "self." and when called from outside you should use "." to access variables or ":" to call functions.
-- Create our baseclass
Animal = class.new();
function Animal:constructor()
self.text = "Unknown animal noise";
end
function Animal:speak()
print(self.text);
end
-- Create a dog, override self.text to bark.
Dog = class.new(Animal);
function Dog:constructor()
Dog.parent.constructor(self);
self.text = "Bark!";
end
-- Create a cat, override self.text to meow.
Cat = class.new(Animal);
function Cat:constructor()
Cat.parent.constructor(self);
self.text = "Meow!";
end
-- Now lets see what happens when we make them speak!
cat = Cat();
cat:speak(); -- The cat should meow
dog = Dog();
dog:speak(); -- And the dog should bark
Destructors & Other Metatable Magic
You may override a class's metatable in order to change its behavior. You might want to override __gc to be a destructor: a function that is called when the object is deleted. You may also want to allow the object to be used with operators such as __add (+), or __sub (-). In order to do this, you'll need to modify the metatable associated with that operation.
getmetatable(Cat).__gc = function ()
print("The cat has died :(");
end
cat = Cat(); -- Make a new cat, it should meow.
cat = nil; -- Now the cat has dies... so sad. The deconstructor should automatically be called now.