CODE

EXPLANATION



Point = {} -- THE CLASS

This is a table that will contain the new() function so that it can be called Point.new() . and resemble the class/object relationship in other languages. Actually, if you called the constructor Pointnew() instead of Point.new() , you wouldn't even need this table. But we use it to get that familiar OOP look.



Point.new = function(x, y) Constructor function, just what you'd expect. You pass in x and y to give the point a location. The purpose of a constructor is to pass back an object, and that's just what Point.new() does. Read on...



local self = {} -- Object to return This is a little tricky. In OOP speak this is the object that will be returned by the constructor. But from a Lua perspective this is just a table to contain all the functions inside Point.new() . The functions and NOT the variables. You know why? The variables x and y are local variables of the outer function, Point.new() -- they are not in self . But the functions are in self , and since an inner function can see its outer function's local variables (this is the basis of closures), the functions inside self can retrieve and manipulate the local variables for Point.new() .



So from a Lua point of view, self is a bag into which to put all the functions declared by Point.new() .



x = x or 0 -- Default if nil

y = y or 0 -- Default if nil There's a lot of Lua in these two simple lines. First of all, a widely used Lua idiom for defaulting a variable looks like this:

a = a or a_default

This is short circuit logic. If a exists then it's set to itself. But if it doesn't exist (perhaps no argument passed into the function), then it's set to a_default .



But even beyond this, remember that in Lua, a functions arguments function EXACTLY like local variables within that function. Therefore, x and y are visible and manipulable to all functions inside of Point.new() .



self.getx = function() return x end

self.gety = function() return y end Getter functions. Put inside table self . Remember that x and y are local to the outer enclosing function (because they're arguments of that function), and therefore are available to the inner function. This is how closures work.



self.setx = function(arg) x = arg end

self.sety = function(arg) y = arg end Setter function. Put inside table self . Same explanation of x and y and closures.



self.show = function(msg)

print(string.format("%s (x,y)=(%d,%d)",

msg, x, y))

end Pretty print's x and y with a message passed in as an argument. Put inside table self . Same explanation of x and y and closures.

return self By the end of Point.new() , self is a bag of functions containing getx, gety, setx, sety and show . By passing this back, the calling program can execute all these functions. If you forget to return self then you'll get an error message something like this:

slitt@mydesk:~$ ./test.lua

/usr/bin/lua: ./test.lua:29: attempt to index global 'mypoint' (a nil value)

stack traceback:

./test.lua:29: in main chunk

[C]: ?

slitt@mydesk:~$



end This ends Point.new() , the constructor.



-- BELOW HERE IS THE MAIN PGM





mypoint = Point.new(2,5) OOP viewpoint: Use class Point to instantiate object mypoint.

Lua viewpoint: Use maker Point.new() to deliver a table of functions to variable mypoint , with state variables held by the closure enclosed by Point.new() .



mypoint.show("Before tweaking:") Pretty-print x and y with a message.



mypoint.setx(2 * mypoint.getx())

mypoint.sety(2 * mypoint.gety()) Set x to double the value returned by getx() . Same with y.

