local Child = require(Child).new()
local Callback = function()
print("Bar")
end
Child.Callback = Callback
Child:Foo()
Child:
local Child = {}
Child.__index = Child
function Child.new()
local self = setmetatable({}, Child)
// fields
return self
end
function Child:Foo()
self.Callback()
end
return Child
When Foo is called in Child, I need the parent to know about it, hence the callback (Is that the right terminology?). I don’t like this implementation because it puts a field that belongs to the Child – Callback – in the Parent script. And if the Parent has a bunch of other classes with their own callbacks, that’s a lot of clutter. What is the best way to do this?
XY Problem
Specifically, I have a LocalScript that controls a customization GUI. It creates a ColorWheel object and three Menu objects. When the ColorWheel color is changed, it fires the callback. Then, the callback assigns the color to whichever menu is active.
The ColorWheel doesn’t know which menu is the active menu because that’s a variable in the LocalScript, which is why it doesn’t simply change the menu’s color itself.
Instead of a callback, maybe try using events instead? You can have a signal (either custom Lua object or a BindableEvent) instead the ColourWheel. When something happens, call :Fire() on the signal. The local script can then either connect directly to the ColourWheel event and pass it on to the menu, or when changing the active menu, disconnect the old from the signal and connect the new one.
E.g.
local colourWheel = ...
local activeMenu
local connection
local function activateMenu(menu)
if connection then
connection:Disconnect()
end
activeMenu = menu
if activeMenu then
connection = colourWheel.signal:Connect(activeMenu.handler)
end
end
I quite like that idea. I was considering using a bindable but opted not to for a purely code approach, which I would still prefer for the sake of improving my OOP game. I’ll give it a shot regardless.
A callback would imply that your child function calls another function or returns out a value to the parent. The parent therefore shouldn’t be putting a function in the child object, it should be passing the function as an argument.
With your current code style, you’re encountering an anti-pattern where you set an index in the child object to call it. The appropriate solution is to pass a callback as an argument so the child function can call it.
local Child = require(Child).new()
local function Callback()
print("Parent func")
end
Child:Foo(Callback)
--
local Child = {}
Child.__index = Child
function Child.new()
local object = setmetatable({
-- fields
}, Child)
return object
end
function Child:Foo(Callback)
print(self.Something)
Callback()
end
return Child
That being said, the parent won’t know about the call unless you use a signal of some kind that is intended to inform the parent that the call happened. For example, you can use a return statement so that when the parent calls the function, the child returns a value to the parent so it can use that value. Otherwise, just use a bindable, it’s still a pure code approach.
Small comment, you’ll notice I changed how the class creates it’s object. Table creation is more performant when you initialise with the values already in over creating a table and then adding elements. You create a templated table with a predefined size versus forcing it to reallocate and expand.