Accessing an objects properties with OOP

I want to be able to access an objects properties. I know I can do this with __index but I can’t seem to get it to work. Basically I want to be able to do this:

object.Position = Vector3.new(0,0,0)

instead of having to do

object.Part.Position = Vector3.new(0,0,0)

Here is my current OOP implementation:

local Object = {}
Object.__index = Object

function Object.new(part, number)
    local self = setmetatable({}, Object)
    
    self.Part = part
    self.Number = number    

    return self
end

return Object

You would not use __index. You should be using __newindex. __newindex is invoked upon t[k] = v or t.k = v.

The issue is that it is not invoked when the key already exists
So you would have to do .Position = nil each time after setting the position

local Object = {}
function Object.__newindex(t, k, v)
    if k == "Position" then
        t.Part.Position = v
    end
end

Where t is the table that Object is the metatable of and k is the key and v is the value
Edit: I had misread your post the first time

I want to note that I want to be able to do this for any property though.

In the case you want to do this for any property, you can try something like this.

function Object.__newindex(t, k, v)
    if t.Part[k] then
        t.Part[k] = v;
    end
end

If that returns errors about a property being nill, you should wrap it in a pcall.

1 Like

In object script:

local Button = {}
Button.__index = Button

function Button.__newindex(self, key, value)
    pcall(function()
        if (self.Object[key]) then
	    self.Object[key] = value
	end
    end)
end

--// Functions \\--
function Button.new(name, iconSize, iconId, hoveredIconId)
    local self = setmetatable({}, Button)
	
    self.Object = script.ButtonPrefab:Clone()

    return self
end

return Button

In another script:

local InventoryButton = self.Modules.Button.new(UDim2.new(0, 46, 0, 46), "rbxgameasset://Images/inventory_normal", "rbxgameasset://Images/inventory_hover")
InventoryButton.Parent = UI

(The parent never gets set to the UI)

Sorry for the long wait, had to mess with this for a while.

local oldInstance = Instance;

local Instance = {};
Instance.__index = Instance;

function Instance.new(InstanceType, StartingParent)
	local self = setmetatable({}, Instance)
	rawset(self, "Object", oldInstance.new(InstanceType));
	self.Parent = StartingParent;
	return self;
end

function Instance.__newindex(self, key, value)
	if self.Object ~=  nil then
		pcall(function()
			self.Object[key] = value;
		end)
	end
end

return Instance;

And in another script:

local Instance = require(game.ReplicatedStorage:WaitForChild("Instance"));
local p = Instance.new("Part");
wait(2)
p.Parent = workspace;

Works fine.

This did work. Thanks!

1 Like

Actually, I am having a problem. It works fine, but if I can’t access or set “values” pertaining to the actual OOP object and not the instance.

Well, here is my weird hacky attempt at fixing your problem. There is probably a better way to do this without using a pcall, but this works for now.

local oldInstance = Instance;

local Instance = {};

Instance.__index = Instance;

function Instance.new(InstanceType, StartingParent)

local self = setmetatable({}, Instance)

rawset(self, "Object", oldInstance.new(InstanceType));

self.Parent = StartingParent;

return self;

end

function Instance.__newindex(self, key, value)

local succ, _ = pcall(function()

self.Object[key] = value;

end)

if not succ then

rawset(self, key, value);

end

end

return Instance;
2 Likes

Sorry for the formatting. Sometimes this site likes to space things out like that, randomly it appears.

It’s fine. It works now. Thanks once again!

2 Likes