Class

From ComputerCraft Wiki
Jump to: navigation, search

Classes can be created in Lua to simplify the creation of large projects by using objects. In Lua, an object is a table which has data and can make use of methods (functions for classes) which are designed to work with the object's data to carry out potentially large or complicated tasks with a minimum of code. Classes are not required for making simple projects, but can be helpful to have when using or creating large projects and APIs, especially when working with other programmers.

Basics of classes

In Lua, classes are built as prototype tables which contain methods and data that other tables can refer to. The simplest example is as follows:

-- Example 1
Prototype1 = {color="black"}
local instance1 = {}
setmetatable (instance1, {__index=Prototype1})
print (instance1.color)

In this example, the program will print "black". This is because we've changed instance1 so that whenever we try to find an attribute that it doesn't have already, it will default to whatever Prototype1 uses for that attribute. Since we never defined instance1.color, it defaults to Prototype1.color which is "black". We can say that instance1 is an object, or that it is an instance of Prototype1.

Methods

Methods are the real reason for creating classes. At the most basic, this can be done as such:

-- Example 2
ImagePrototype = {data={}}

function ImagePrototype.printData (instance)
  print (instance.data)   
end

local image1 = {data="1,1,Black;"}
setmetatable (image1, {__index=ImagePrototype})
ImagePrototype.printData(image1)

This program will print "1,1,black;". We can make it a little bit more efficient if we use colons ':'. Although all attributes of table and objects can be accessed like objectName ["attributeName"] or objectName.attributeName, there is a special trick we can use for methods. Using a colon, we can say objectName:methodName() and we will automatically make it so that the first variable we give the method is the object that we were referring to. In addition, we can use this trick when we write methods. By saying className:methodName, the method will automatically have an initial variable called self. 'Self' is the standard term used across many programming languages to refer to the object that a method is working with. Here's an example of how we can simplify this code:

-- Example 3
ImagePrototype = {data={}}

function ImagePrototype:printData ()
  print (self.data)   
end

local image1 = {data="1,1,Black;"}
setmetatable (image1, {__index=ImagePrototype})
image1:printData()

Now we still still print "1,1,Black;", but we've made things a little bit neater and easier.

Initialization

Instead of using setmetatable after every time we create an instance, we can simplify things a little bit more by including that process in the class with an initialization function. Here's an example:

-- Example 4
ImagePrototype = {data={}}

function ImagePrototype.__init__ (data)
  local self = {data=data}
  setmetatable (self, {__index=ImagePrototype})
  return self
end

function ImagePrototype:printData ()
  print (self.data)   
end

local image1 = ImagePrototype.__init__ ("1,1,Black;")
image1:printData()

Now we're still printing "1,1,Black;", but we only need one line of code to create an instance of ImagePrototype, and one line to do the printing. The last two lines in this example involve a lot less writing than the last three lines in example 2.

Callable classes

We can simplify things even further and achieve some interesting results by making classes act like functions. To do this, we use setmetatable again, but now we're changing __call instead of __index. Here's an example:

-- Example 5
ImagePrototype = {data="Original"}

function ImagePrototype.__init__ (baseClass, data)
  self = {data=data}
  setmetatable (self, {__index=ImagePrototype})
  return self
end

setmetatable (ImagePrototype, {__call=ImagePrototype.__init__}) --Makes ImagePrototype(...) act like ImagePrototype.__init__ (ImagePrototype, ...)

function ImagePrototype:printData ()
  print (self.data)   
end

local image1 = ImagePrototype ("1,1,Black;")
image1:printData()

Now we get the same output, but the last two lines have become even simpler, especially when compared with the last three lines in example 2.

Callable classes can also be used in other cases, for example if you want to make a class which acts like a function.

Should add information about getters and setters, private attributes, inheritance, superclasses, decorators and docstrings, etc.

See also

External links