Help understanding module scripts and metatables

Module script:

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()

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?

2 Likes

Read the following.

3 Likes

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()

Here is the code btw.

I would suggest reading the topics above I said.

2 Likes

Sorry this is my first time posting, I think I’ve compiled it correctly now

1 Like

Yea… better than previously. Also can you not just do what you said? Use Class.__index = Class? I am sure that would well obviously. Do it.

That’s not his question.

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

1 Like

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.

EDIT: I didn’t reply anyone. Sorry if bothered.

2 Likes

Ohh! Like I didn’t know that. (Sarcasm) I asked him the question. Not answered his question.

Oh, my bad then. I interpreted it differently xD

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