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!