So I'm messing around with metatable's, i understand how setmetatable and __index and __newindex works, but i don't understand inheritance and multiple inheritance yet quite well.
My Problem: I try to get the variable 'h' but it prints nil, everything else is fine, what am i doing wrong here? How can i have nested metatables connected to each other, like fallback when one fails it goes to other.
Here's Code:
local Window = { ClassName = 'ScrollingFrame', Size = UDim2.new(0,0,0,0), CursorColor3 = Color3.fromRGB(255,255,255), } Window.__index = Window Window.metatable = {} Window.metatable.__index = { getClassName = function(self) return self.ClassName end } setmetatable(Window, Window.metatable) --I Can't to seem to get "h" variable from here for some reason?,Why? Window.LockedProperties = {} Window.LockedProperties.__index = {h = 999} setmetatable(Window.metatable, Window.LockedProperties) --Constructor function Window.new() return setmetatable({},Window) end local w = Window.new() print(w.Size) print(w.h) print(w:getClassName())
I believe you went about it wrong.
As far as I know, the __index
metamethod is supposed to be a function, not a table, which I believe is the main error.
-->> VALUES local Window = {Size = UDim2.new(0,0,0,0),ClassName = "ScrollingFrame"} Window.LockedProperties = {h = 999} Window.__index = Window -->> FUNCTIONS Window.Metatable = { -->> one table for everything, no need for heaps __index = function(table,index) return table.LockedProperties[index] end -->> you should also use the other function that fires when a value gets set to prevent the locked properties from being changed } Window.LockedProperties.__newindex = function(table,index,value) warn("Cannot set new value to LockedProperties") end setmetatable(Window.LockedProperties,Window.LockedProperties) setmetatable(Window,Window.Metatable) function Window.new() return setmetatable({},Window) end function Window:GetClassName(self) return self.ClassName end -->> TESTING local w = Window.new() print(w.Size,w.h) -->> it should print: 0,0,0,0 999
To explain:
You would want to set everything first so that you know what is where. I like to organise my code when it gets long or complicated - it's very useful.
Next, I create the metatable, and make the __index
function that returns the locked property (that's literally it all it needs to do). After that, I simply set the metatable, then create the other functions and methods.
Note that when setting a function inside a table, it will by default be indexed by .
and not :
. The latter can only be indexed when you set it like I did.
EDITS:
So I tried to come up with a read-only system, but I got stumped. __newindex
only fires when a new value and index are created, not when a value is changed.
My only other idea is to move the LockedProperties upon creation into a different entity, and index using the table's ID (tostring(table)
).
But I don't have time to work on that, so good luck ;)
Please comment any problems/questions you have. Hope I helped!
~TDP