Classes

From SolarStrike wiki
Jump to: navigation, search

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.