function Class.new(name)
local object = {}
object.Name = name
setmetatable(object, Class)
return object
end
function Class.Hello()
print(“Hello”)
end
return Class
Script:
local module = require(script.Parent.Base)
local obj = module.new(“Child”)
print(obj.Name)
print(getmetatable(obj))
obj.Hello()
Error: ServerScriptService.Script:8: attempt to call a nil value
I want to preface this with I know i can fix this by putting:
Class.__index = Class
on the second line of the module script. My problem is I cant wrap my head around how this works.
On line 6 of my script I can print the metatable for my child object and it returns a table showing the Hello function aswell as the New function, however when i try to run them I get an attempt to call nil value error.
If these functions are in the childs metatable and it can see them, why can’t it access them? and how does setting the index of the class to itself solve the problem?
First of all can you please compile your code into a textbox? By putting 3 backquotes “`” above and below the code?
local Class = {}
function Class.new(name)
local object = {}
object.Name = name
setmetatable(object, Class)
return object
end
function Class.Hello()
print("Hello")
end
return Class
**Script:**
local module = require(script.Parent.Base)
local obj = module.new("Child")
print(obj.Name)
print(getmetatable(obj))
obj.Hello()
Basically (from what I know, please correct me if I’m wrong on any of this), without Class.__index = Class, they aren’t. When you do that, and call Hello, you’re essentailly having it look for obj[Hello], and since it can’t find it it looks for Class[Hello]. That’s what __index does. When it inevitably can’t find the index in obj, it checks inside of class since the __index is class. Unless you’re using __index, it’ll just check obj, not find it, and error
The self keyword is the only way to access the metatable. If you use the Class table instead of self, you will not be able to access the data in the metatable. You can only use self with the Class:Hello() function, not with Class.Hello(). You need to use : instead of . to access it. “self” is basically the “Object” variable you used in your module script.
The __index metamethod is used to create variables that doesn’t exist (basically). If you try to access a value that is not stored in the table, it will return nil unless you use __index. The reason we set Class.__index = Class is that when you create a variable with self, such as self.Object = "Object", even if there is no data stored with that name, it will be passed into the table so you can use it in other functions. There is no point of using metatable without metamethods. For example:
-- Without using __index
self.Object = "object" -- it'll print nill
With using __ index
self.Object = "object" -- it'll print "object"
I fixed your script over here:
local Class = {}
Class.__index = Class
function Class.new(name)
local object = {}
object.Name = name
setmetatable(object, Class)
return object
end
function Class:Hello()
print("Hello", self.Name)
end
return Class
**Script:**
local module = require(script.Parent.Base)
local obj = module.new("Child")
print(obj.Name)
print(getmetatable(obj))
obj:Hello()
Apologizing for my bad english if you have something that you didn’t understand you can tell me.