How to save a function of an Object/table to a variable to be called from this variable in Lua?

56 Views Asked by At

I'm experimenting with Lua OOP (Object Oriented Programming) but I'm experiencing some issues.

Here is a sample code with comments:

Object = {string = "Default"}

function Object:new()
    local o = {}
    setmetatable(o, {__index = self})
    -- o.string = "Default"
    return o
end

function Object:SayHi(input)
    if input == nil then
        input = ""
    else
        local temp = input
        input = " " .. temp
    end
    print("Hi!" .. input)
end

function Object:CallHiFunct()
    local temp = "Called from CallHiFunct"
    self:SayHi(temp)
end

function Object:PrintString()
    print(self.string) -- Variable named string from Object
end

object1 = Object:new() -- Returns new metatable to object1
object1:SayHi() -- Prints Hi!
object1:CallHiFunct() -- Prints Hi! Called from CallHiFunct
object1:PrintString() -- Prints Default

print()
print()

funct_object1 = object1.SayHi
funct_object1() -- Prints Hi!

funct2_object1 = object1.PrintString
funct2_object1() -- Error: attempt to index a nil value (local 'self')

funct2_object1 = object1:PrintString() -- if object1:PrintString Error: function arguments expected near 'funct2_object1'
funct2_object1() -- Error: attempt to call a nil value (global 'funct2_object1')

I'm trying to save a function from an object/table but I'm having problems with self being nil.

How can I properly do this to keep the function with the object?

.

The reason why I'm doing this is because I'm using a function specified in a library which accepts function as an argument.

I think something like this:

function Example(funct)
    funct() -- calls it here
end

To be exact the function is actually: GUI:AddButton(arguments...):AddEventHandler(event, funct)

(event: when it is activated, funct: to call when activated)

but I'm not exactly sure what is inside.

Anyway. Ignoring this library is it possible to save a function from an "object" to variable to be called from this variable?

(I was unable to find any answer. I it already has been asked then link the question with the answers please.)

Thanks.

1

There are 1 best solutions below

1
Oka On BEST ANSWER

table:function(arguments) is purely syntactic sugar for table.function(table, arguments).

(In the body of the function definition table is the implicit self, when defined with colon syntax.)

As you have seen, this assignment

funct2_object1 = object1.PrintString

does not carry any information about object1 with it, and so this function call

funct2_object1()

errors out, looking for an explicit first argument to fill the role of self.

If you had called funct2_object1(object1) the function would behave as expected.


Given this callback-style function

function Example(funct)
    funct() -- calls it here
end

it sounds like what you want is to create a closure around your OOP-style call, which you can do by enclosing it with a function (anonymous or otherwise).

For example:

local Object = {}

function Object:new(data)
    return setmetatable({ data = data }, { __index = self })
end

function Object:do_something()
    print('Hello from', self, self.data)
end

local thing = Object:new(42)

----

local function Example(funct)
    funct()
end

Example(function ()
    thing:do_something()
end)
Hello from  table: 0x55c65be628c0   42