Is it possible to create a “weak reference”, a weak table but instead of the entire table being weak it’s just a single key/value
I have 2 classes, Class1 and Class2. Class1 references Class2, so when Class2 gets destroyed it won’t be GCd because of the reference in Class1
local Class1 = Class.new()
local Class2 = Class.new()
Class1.SignalClass = Signal.new() --This is the only reference to this "signal" object, so I cannot make Class1 a weak table
Class1.AnotherClass = Class2 --I want this to be a "weak reference"
Class2:Destroy()
Class2 = nil --Won't get GCd
Personally I would use setters/getters for this scenario. I think hiding the weakness of a reference behind an assignment has the potential to confuse the user of your module (which might be yourself ).
If you really wanted to though, I suppose you could hide the implementation from the user with __newindex. It might require a bit of a different approach to your OOP though, since the metatable is defined in the object creation itself.
-- untested but makes sense to me :)
local Class = {}
-- removed on purpose, see later comments
-- Class.__index = Class
local Class_WEAK_KEYS = {
"AnotherClass" = true,
"AnotherWeakKey" = true
}
function Class.new()
local weakRefs = setmetatable({}, {
__mode = "v" -- or "kv" depending on your needs
})
setmetatable(obj, {
__index = function(t, k)
if Class_WEAK_KEYS[k] then
-- return weak reference instead
return weakRefs[k]
else
-- replaces the usual Class.__index = Class that you see
-- in some OOP implementations
return Class[t]
end
end,
__newindex = function(t, k, v)
if Class_WEAK_KEYS[k] then
-- assign weak reference instead
weakRefs[k] = v
else
rawset(t, k, v)
end
end
})
return obj
end