Is it possible to connect events (such as activated) when using OOP?

So, I recently learnt OOP (Object Oriented Programming), and I was experimenting with a window system.
I was wondering if it’s possible to embed events (such as button.Activated) into the constructor function (or any other parts of a module) into a moduleScript?

1 Like

This is certainly possible! You have a few options here…
Using a standard Lua class, you can choose to create a GuiButton as your base class, and then as the class gets instantiated, through inheritance this method is available to you from your new window class.

local Window = {}
Window.__index = Window

local HttpService = game:GetService("HttpService")

function Window.new()
    local self = setmetatable(Instance.new("ImageButton"), Window)

    return self
end

function Window:Destroy()
    self:Destroy()
end

return Window

Were you to require this class somewhere else, you could then do:

local function doSomething()
    --Do something here
end

local newWindow = Window.new()
newWindow.Activated:Connect(doSomething)

If you are looking for something more… customizable, you can use Signals:

With this you need only set up the signal in your class, and within some other method, you can fire the signal and receive the connection somewhere else, and respond accordingly.

local Window = {}
Window.__index = Window

local HttpService = game:GetService("HttpService")
local Signal = require(game:GetService("ReplicatedStorage"):WaitForChild("Signal"))

function Window.new()
    local self = setmetatable({}, Window)

    self.Opened = Signal.new()

    return self
end

function Window:OpenWindow()
    self.Opened:Fire()
end

function Window:Destroy()
    self:Destroy()
end

return Window
2 Likes

Thank you for your solution!
However, is it possible to connect the activated event to a child of the base window?

What I’m trying to say is I want to make the X button functionable in the module so I don’t need to do it manually through every single script that uses it.

The main window is a CanvasGroup, and it has a few frames inside it. One of these frames contains the X button.

image

The CanvasGroup is cloned whenever a window.new() function fires. I’m just asking if it’s possible to simply do

windowClone.UpFrame.X.Activated:Connect(function()
     windowClone:Close()
end)

inside the constructor function?

1 Like

Yes, it is possible. OOP is just a table with constructor and functions.

1 Like

Why not?

local UiButton = {}
UiButton.__index = UiButton 

function UiButton.new()
    local newObj = {}
    
    -- assuming a complex hierarchy
    -- with lots of frames and other elements
    local newButtonInstance = Instance.new("Frame") 
    --create UI here

    newObj.Instance = newButtonInstance
    newObj.Activated = newButtonInstance.ImageButton.Activated

    newObj = setmetatable(newObj, UiButton)

    return newObj
end

function UiButton:Destroy()
    self.Instance:Destroy()
end

return UiButton

Now you could just do:

local newButton = UiButton.new()
newButton.Activated:Connect(myHandler)
1 Like

No. I am wondering if

is possible in the module itself. Like right after the cloning and stuff in window.new()

something like this:

function UiButton.new()
    local newObj = {}
    
    -- assuming a complex hierarchy
    -- with lots of frames and other elements
    local newButtonInstance = Instance.new("Frame") 
    --create UI here

    newObj.Instance = newButtonInstance
    newObj.Activated = newButtonInstance.ImageButton.Activated

    -- doing a function whenever the 'newObj.Activated' event happens
    
    newObj = setmetatable(newObj, UiButton)

    return newObj
end
1 Like

Just a quick note, but setmetatable actually requires two table arguments, not an instance of an object, so your first sample would throw an error.

2 Likes

Sure! Thats completely possible. In fact, thats what you would do if you wanted some default behaviour for the activated event.

If you could tell me what lead you to think it might not be possible, I could assist you better.

Events can be connected wherever you have the instance’s reference. Since you have the reference inside the constructor (.new()) you can connect to any event :slight_smile:

1 Like

Alright. This is my constructor function:

function window.new(player:Player, name:string, params:{})
	if not player then warn("No player parameter!") return end
	local class = setmetatable({}, window)
	
	local w = game.ReplicatedStorage.Resources.Window:Clone()
	w.Name = name or "Window"
	w.Parent = player.PlayerGui.WindowGui
	w.Visible = false
	w.GroupTransparency = 1
	
	local sx = params and params.sizeX or 400
	local sy = params and params.sizeY or 200
	local px = params and params.posX or 200
	local py = params and params.posY or 100
	local prior = params and params.priority or 1
	
	w.Size = UDim2.new(0, sx, 0, sy)
	w.Position = UDim2.new(0, px, 0, py)
	w.ZIndex = prior
	
	class.XClicked = w.UpFrame.X.Activated -- Tried out your solution lol
   
 --[[w.UpFrame.X.Activated:Connect(function()
        if w.GroupTransparency == 0 then
            self:Close()
        end
    end)
    ]]
	class.Window = w
	
	return class
end

Also, when I try to connect the function in the main script (NewW.XClicked:Connect(function)), it doesn’t run at all. When I try to print out NewW.XClicked, I get “Signal activated” in the output.

1 Like

Nevermind, I found the solution. I guess my first solution of putting it in the constructor function worked. The ONLY reason it didn’t is because I used Activated, and for some reason, it didn’t feel like firing. Whatever.

Big thanks to everyone for helping!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.