Is setmetatable(Object, nil) important?

I see from a lot of community module classes that they destroy Objects like this:

function Object:Destroy()
   setmetatable(self, nil)
   table.freeze(self)
end

This struck me as odd because I’ve always been doing Destroys like this:

function Object:Destroy() -- I wouldn't use a function for one line of code but you get the point
   self = nil
end

What is the difference and what are the big no-no’s in my method compared to the one at the top? I would like to know.

The best way to delete custom class objects would be to remove any reference to any values inside them. For example, if your object has any references to any Instances, or uses any Instances, when the :Destroy() is called, destroy those Instances, and remove the references to those Instances.

After that, remove every single value from the table(set them to nil), and finally, set the self to nil.
After the :Destroy() call on the object, set the variable for that object to nil as well.
This way, the garbage collector will pick that object up as it has no remaining references, and clear the memory.

this does nothing but make the variable self equal nil

1 Like

Setting the metatable to nil and freezing the table ensures that the object is completely unusable after it’s destroyed, which is the desired behavior. You should additionally call table.clear to clear all references to other objects that may still be inside the table.

An ideal destroy method (of course, you have to disconnect connections or call the destroy functions of any component objects before this):

setmetatable(self, nil)
table.clear(self)
table.freeze(self)

Setting self to nil does nothing; it only sets the reference to the table to nil and does not actually modify anything, as @batteryday explained.

Try running the following in the command bar. You should see that the object is completely unchanged.

local Object = {}
Object.__index = Object

function Object.new(...)
	return setmetatable({...}, Object)
end

function Object:Destroy()
	self = nil
end

local ob = Object.new(1, 2, 3)
print(ob) -- {1, 2, 3}

ob:Destroy()
print(ob) -- {1, 2, 3}
2 Likes

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