How can I store properties & a table of functions inside an object? (metatables?)

Pretty confused on what to name this lol, still very much trying to get the hang of metatables & so on. Here’s my module script, the issue is that I’m trying to set properties of the Item, eg: it’s name and rarity, while also storing a table of it’s functions by setting the metatable to the module table.

local ItemsModule = {}
ItemsModule.__index = ItemsModule

function ItemsModule:new(name, rarity)
	self.ItemName = name
	self.ItemRarity = rarity
	self.functions = {}
	setmetatable(self.functions, ItemsModule)
end

function ItemsModule:doprint()
	print(self.ItemName, self.ItemRarity)
end

return ItemsModule

Then I try to call it in this script:

local ItemsModule = require(script.ItemsModule)
local Item = ItemsModule:new("green brick", "legendary")

Item:doprint()

The error:
Players.Anumth.PlayerScripts.LocalScript:4: attempt to index nil with ‘doprint’ -

I should also state I wish to accomplish this without the usage of any external modules for OOP.

1 Like

The issue is that the :new functions returns nothing. This means the Item variable is nil hence nothing exist and the error pops up.

You could have found this out by printing Item, whenever you get any nil error in your life, this will lead you to trace back your errors and solve problems quicker and faster.

print(Item) --print nil

If you have looked at a proper OOP tutorial you will find out that they place a specific line in the .new function to return the property table:

function Car.new(position, driver, model)
    local newcar = {}
    setmetatable(newcar, Car)
--some property setting stuff for newcar
    return newcar --this is pretty significiant
end

I recommend understanding the steps and lines of code or at least copy pasting like in this OOP tutorial for a car object, just replace the name Car with an object name you want via find and replace all and insert the properties you want and It’ll work.

OOP boiler plate for a car
--module script called Car in game.ReplicatedStorage
Car = {}
Car.__index = Car

function Car.new(position, driver, model)
    local newcar = {}
    setmetatable(newcar, Car)

    newcar.Position = position
    newcar.Driver = driver
    newcar.Model = model

    return newcar
end

function Car:Boost()
    self.Speed = self.Speed + 5
end

return Car
3 Likes

you forgot to return the new object:

function ItemsModule:new(name, rarity)
	self.ItemName = name
	self.ItemRarity = rarity
	self.functions = {}
	return setmetatable(self.functions, ItemsModule)
end

but there is still an error. The fields are being assigned to the class (as static fields) and not to the new object. You could solve it like this.

function ItemsModule:new(name, rarity)
	local o = {}
	o.ItemName = name
	o.ItemRarity = rarity
	return setmetatable(o, ItemsModule)
end

Or you can also implement more standard OOP:
https://www.lua.org/pil/16.html
https://www.tutorialspoint.com/lua/lua_object_oriented.htm

3 Likes

Sorry I didn’t mark this as a solution, both replies equally helped me out tremendously!

1 Like