[SOLVED] Dynamically create methods for a class.

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
LeNitrous
Prole
Posts: 29
Joined: Tue Sep 08, 2015 3:25 am

[SOLVED] Dynamically create methods for a class.

Post by LeNitrous »

I am trying to hook a number of love handlers to a class. All they have to do is to propagate the call to all of the children. Although there are so many handlers I decided to list them all to a table then attempt to generate them through a for loop.

The code shown below is what I described above.

Code: Select all

local callbacks = {
    "update", "keypressed", "keyreleased", "textedited", "textinput",
    "mousemoved", "mousepressed", "mousereleased", "wheelmoved",
    "gamepadaxis", "gamepadpressed", "gamepadreleased", "joystickadded",
    "joystickaxis", "joystickhat", "joystickpressed", "joystickreleased",
    "joystickremoved", "touchmoved", "touchpressed", "touchreleased"
}

for _, v in ipairs(callbacks) do
    local func = function(...)
    local args = {...}
    self.children:forEach(function(i, child)
        if type(child[v]) == "function" then
            child[v](unpack(args))
        end
    end)
end

self.class.__declaredMethods[v] = func
self.class.__instanceDict[v] = func
Is it possible in the first place? If so, what am I doing wrong?

Because this works

Code: Select all

self.update = function(dt)
    print "Hello World"
end
But this doesn't

Code: Select all

function Game:update(dt)
    print "Hello World"
end
Notes
  • I'm also using kikito's middleclass for OOP.
  • self.Children is a class similar to C#'s List.
  • Although I can use love.handlers, I decided to list only input handlers.
Attachments
quick.love
(73.02 KiB) Downloaded 112 times
Last edited by LeNitrous on Sat Jun 08, 2019 1:42 pm, edited 1 time in total.
grump
Party member
Posts: 947
Joined: Sat Jul 22, 2017 7:43 pm

Re: Dynamically create methods for a class.

Post by grump »

I'm sorry, I can't help with the middleclass stuff, just a note: This forEach construct for arrays is tempting to implement and looks clean, but be aware that it incurs a performance penalty in most cases. Callbacks like this are slower than loops and iterators in LuaJIT, and creating anonymous functions in a loop generates garbage.
User avatar
LeNitrous
Prole
Posts: 29
Joined: Tue Sep 08, 2015 3:25 am

Re: Dynamically create methods for a class.

Post by LeNitrous »

I took down the forEach part. Credits to AuahDark for helping me. All I need was to change a few things around the code.

For those wondering, it's now:

Code: Select all

local callbacks = {
    "update", "keypressed", "keyreleased", "textedited", "textinput",
    "mousemoved", "mousepressed", "mousereleased", "wheelmoved",
    "gamepadaxis", "gamepadpressed", "gamepadreleased", "joystickadded",
    "joystickaxis", "joystickhat", "joystickpressed", "joystickreleased",
    "joystickremoved", "touchmoved", "touchpressed", "touchreleased"
}

for _, v in ipairs(callbacks) do
    Container[v] = function(self, ...)
        local args = {...}
        for _, child in ipairs(self.children) do
            if type(child[v]) == "function" then
                child[v](unpack(args))
            end
        end
    end
end
Container is the class.
MrFariator
Party member
Posts: 559
Joined: Wed Oct 05, 2016 11:53 am

Re: [SOLVED] Dynamically create methods for a class.

Post by MrFariator »

Just quick two cents, I think you are creating unnecessary garbage by wrapping the varargs into a table, only to unpack it a few lines later. This kind of code, unpack() in particular, can be rather costly if those callbacks are going to be called often.

Code: Select all

for _, v in ipairs(callbacks) do
    Container[v] = function(self, ...)
        for _, child in ipairs(self.children) do
            if type(child[v]) == "function" then
                child[v](...)
            end
        end
    end
end
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot] and 11 guests