Method environment extension table - tanevnikola/lua-oos GitHub Wiki
Let start by examining the code from the first example
local ft = require "lib.oos"
ft.class.Test() {
{print = print;};
constructor = function()
print("Hello World!")
end;
}
local instance = ft.class.Test();
You might have noticed the strange table at the beginning of the class definition: {print = print;}. This is the method environment extension table. By default all the methods have very limited access and do not directly see the global _G table.
Consequentially, this will fail:
local ft = require "lib.oos"
ft.class.Test() {
constructor = function()
print("Hello World!")
end;
}
local instance = ft.class.Test();
Output
[Error] ?:-1: attempt to call a nil value (field 'print')
So by adding the method extension table at the beginning of the class (must be with index / or key [1]) we can extend the method environment. This is what we did in the first example, by extending the method environment with the print function we got access to the global print function.
Limitation: We can only add functions or tables (and classes, since they are basically tables) to the Method Environment Extensions table.
Capture and/or override global functions
This table is mostly used to capture functions defined in the global _G table so they can be accessed inside the methods of the class. This provide a very useful and convenient mechanism for sandboxing.
Lets override the print function for the instances of this class only
ft.class.Test() {
{
print = function(x) print "Hello " ... x; end;
};
print = function(msg)
print(msg);
end;
}
local instance = ft.class.Test();
instance.print("World!");
print("World!");
Output
Hello World!
World!
you can see that the print function behavior is modified if accessed from inside the class methods, but it stays the same old print function when used from any other place in the code.
static data
In the method extension table, if you add a table field, each instance will have the reference to the same table which means that the fields inside will be the same for each instance of the class.
Best shown with an example
ft.class.Test() {
{
print = print,
staticData = {
message = "Hello";
}
};
constructor = function()
print(staticData.message);
end;
modifyMessage = function(x)
staticData.message = x;
end;
}
local instance1 = ft.class.Test();
instance1.modifyMessage("World!");
local instance2 = ft.class.Test();
Output
Hello
World!