OOP - I'm making something wrong help

Hello! so basically, it look’s like there’s an error while I try to give the function to house: code

local Houses = {}
Houses.__index = Houses
local OwnedHouses = {}

function Houses.new(House)
  return setmetatable({owner = nil, touch = House.TouchPart, sign = House.Textt.SurfaceGui.TextLabel}, Houses)
end

function Houses:Sell(self)
	self.owner = nil
	self.sign.text = "No owner!"
end

function Houses:GiveFunction(House)
	self.touch.Touched:Connect(function(hit)
		print("Touched")
		if hit.Parent:FindFirstChild("Humanoid") then
			local Player = game.Players:GetPlayerFromCharacter(hit.Parent)
			
			if self.owner == nil  then
				print("yes")
				
				self.owner = Player.Name
				self.sign.Text = Player.Name
                OwnedHouses[Player.UserId] = self
				Player["PlayerGui"]["ScreenGui"]["TextButton"].Visible = true
				Player["PlayerGui"]["ScreenGui"]["TextButton"].MouseButton1Click:Connect(function()
					House:Sell(OwnedHouses[Player.UserId])
					Player["PlayerGui"]["ScreenGui"]["TextButton"].Visible = false
				end)
			end
		end
	end)
end

All works, but, ReplicatedStorage.Handler:28: attempt to index upvalue ‘House’ (a nil value) is the line when I do House:Sell() is there a better way to make this or to make it more efficient? and to make it works, obviously

First, when you do function Thing:Method, it automatically makes the “self” parameter as the first parameter. When you write Houses:Sell(self), Lua sees this as Houses.Sell(self, self) which I assume is not your intended behavior.

Second, for your GiveFunction method, are you sure you didn’t intend to store House in the object when you construct it during new? If you did, you could just do self.House instead of having a weird dangling House parameter.

2 Likes

I made this:

local HouseHandler = require(game.ReplicatedStorage.Handler)
_G["Houses"] = {}

for i,v in ipairs(workspace.House:GetChildren()) do
   local new = HouseHandler.new(v)
   HouseHandler.GiveFunction(new)
   
end

When I try it it doesn’t works

  13:44:55.962 - ReplicatedStorage.Handler:28: attempt to index upvalue 'House' (a nil value)
13:44:55.963 - Stack Begin
13:44:55.963 - Script 'ReplicatedStorage.Handler', Line 28
13:44:55.964 - Stack End
function Houses:Sell()
	self.owner = nil
	self.sign.text = "No owner!"
end

function Houses:GiveFunction(House)
	self.touch.Touched:Connect(function(hit)
		print("Touched")
		if hit.Parent:FindFirstChild("Humanoid") then
			local Player = game.Players:GetPlayerFromCharacter(hit.Parent)
			
			if self.owner == nil and not table.find(OwnedHouses, Player.UserId) then
				print("yes")
				
				self.owner = Player.Name
				self.sign.Text = Player.Name
                OwnedHouses[Player.UserId] = self
				Player["PlayerGui"]["ScreenGui"]["TextButton"].Visible = true
				Player["PlayerGui"]["ScreenGui"]["TextButton"].MouseButton1Click:Connect(function()
					House:Sell()
					Player["PlayerGui"]["ScreenGui"]["TextButton"].Visible = false
				end)
			end
		end
	end)
end

How I fix it?

You should be indexing the Text property, not the text property (which does not exist), since you’re trying to modify the properties of a TextLabel.

Edited

I believe the problem is that you are calling the GiveFunction method using the dot ( . ) operator instead of the colon ( : ) operator. As a result, you are passing your new house as the “self” variable, not as the “House” variable.

I believe the following should work. That said, I would recommend refactoring as described by Autterfly.

local newHouse = HouseHandler.new(v)
HouseHandler:GiveFunction(newHouse )

You’re kind of missing the point of OOP.

local new = HouseHandler.new(v)
new:GiveFunction()

The .new() is a normal function because it’s defined with .. The :GiveFunction() is a method that uses a self object because it’s implicit in the :.

Now, when you call new:GiveFunction() you aren’t passing a House parameter anywhere. What I suggest you do is modify to .new() constructor to store the House. Ex:

function Houses.new(House)
    return setmetatable({house = House, --[[your other stuff here]]}, Houses)
end

Now in your other function, remove the House parameter:

function Houses:GiveFunction()
    -- your code here
end

Whenever you want to refer to your house inside :GiveFunction() now, you can just use self.house.

2 Likes

Still, not working

local Houses = {}
Houses.__index = Houses
local OwnedHouses = {}

function Houses.new(House)
  return setmetatable({house = House,owner = nil, touch = House.TouchPart, }, Houses)
end

function Houses:Sell()
	self.owner = nil
	self.house.Textt.SurfaceGui.TextLabel.Text = "No owner!"
end

function Houses:GiveFunction(House)
	self.touch.Touched:Connect(function(hit)
		print("Touched")
		if hit.Parent:FindFirstChild("Humanoid") then
			local Player = game.Players:GetPlayerFromCharacter(hit.Parent)
			
			if self.owner == nil and not table.find(OwnedHouses, Player.UserId) then
				print("yes")
				
				self.owner = Player.Name
				self.house.Textt.SurfaceGui.TextLabel.Text = Player.Name
                OwnedHouses[Player.UserId] = self
				Player["PlayerGui"]["ScreenGui"]["TextButton"].Visible = true
				Player["PlayerGui"]["ScreenGui"]["TextButton"].MouseButton1Click:Connect(function()
					House:Sell()
					Player["PlayerGui"]["ScreenGui"]["TextButton"].Visible = false
				end)
			end
		end
	end)
end

return Houses

it says: ReplicatedStorage.Handler:28: attempt to index upvalue ‘House’ (a nil value)

Line 28 = House:Sell()

Main script:


local HouseHandler = require(game.ReplicatedStorage.Handler)
_G["Houses"] = {}

for i,v in ipairs(workspace.House:GetChildren()) do
	local new = HouseHandler.new(v)
	new.GiveFunction(new)
	
end
local Houses = {}
Houses.__index = Houses
local OwnedHouses = {}

function Houses.new(House)
  return setmetatable({house = House,owner = nil, touch = House.TouchPart, }, Houses)
end

function Houses:Sell()
	self.owner = nil
	self.house.Textt.SurfaceGui.TextLabel.Text = "No owner!"
end

function Houses:GiveFunction()
	self.touch.Touched:Connect(function(hit)
		print("Touched")
		if hit.Parent:FindFirstChild("Humanoid") then
			local Player = game.Players:GetPlayerFromCharacter(hit.Parent)
			
			if self.owner == nil and not table.find(OwnedHouses, Player.UserId) then
				print("yes")
				
				self.owner = Player.Name
				self.house.Textt.SurfaceGui.TextLabel.Text = Player.Name
                OwnedHouses[Player.UserId] = self
				Player["PlayerGui"]["ScreenGui"]["TextButton"].Visible = true
				Player["PlayerGui"]["ScreenGui"]["TextButton"].MouseButton1Click:Connect(function()
					Houses:Sell()
					Player["PlayerGui"]["ScreenGui"]["TextButton"].Visible = false
				end)
			end
		end
	end)
end

return Houses

Ok I edited a little bit, but not it says:

14:12:22.033 - ReplicatedStorage.Handler:11: attempt to index field ‘house’ (a nil value)

14:12:22.034 - Stack Begin

14:12:22.034 - Script ‘ReplicatedStorage.Handler’, Line 11 - method Sell

14:12:22.034 - Script ‘ReplicatedStorage.Handler’, Line 28

Line 11 = self.house.Textt.SurfaceGui.TextLabel.Text = “No owner!”

Try:

-- self.house:Sell() -- [Edit] Incorrect. self.house refers to the house part / model
self:Sell()

Also, I believe you want to call the “GiveFunction” with the colon operator so that “self” will be passed as the first parameter.

Now it’s saying
ReplicatedStorage.Handler:15: attempt to index local ‘self’ (a nil value)

Are you calling the “GiveFunction” using the colon operator?

local HouseHandler = require(game.ReplicatedStorage.Handler)
_G["Houses"] = {}

for i,v in ipairs(workspace.House:GetChildren()) do
   local newHouse = HouseHandler.new(v)
   newHouse:GiveFunction()
end

Ok so, this is my current:

local HouseHandler = require(game.ReplicatedStorage.Handler)
_G["Houses"] = {}

for i,v in ipairs(workspace.House:GetChildren()) do
	local new = HouseHandler.new(v)
	new.GiveFunction(new)
	
end

Module:

local Houses = {}
Houses.__index = Houses
local OwnedHouses = {}

function Houses.new(House)
  return setmetatable({house = House,owner = nil, touch = House.TouchPart, }, Houses)
end

function Houses:Sell()
	self.owner = nil
	self.house.Textt.SurfaceGui.TextLabel.Text = "No owner!"
end

function Houses:GiveFunction(House)
	self.touch.Touched:Connect(function(hit)
		print("Touched")
		if hit.Parent:FindFirstChild("Humanoid") then
			local Player = game.Players:GetPlayerFromCharacter(hit.Parent)
			
			if self.owner == nil and not table.find(OwnedHouses, Player.UserId) then
				print("yes")
				
				self.owner = Player.Name
				self.house.Textt.SurfaceGui.TextLabel.Text = Player.Name
                OwnedHouses[Player.UserId] = self
				Player["PlayerGui"]["ScreenGui"]["TextButton"].Visible = true
				Player["PlayerGui"]["ScreenGui"]["TextButton"].MouseButton1Click:Connect(function()
					self.Houses:Sell()
					Player["PlayerGui"]["ScreenGui"]["TextButton"].Visible = false
				end)
			end
		end
	end)
end

return Houses

Just realized you should call the “Sell” method as follows (inside GiveFunction):

self:Sell()

Using “self.house:Sell()” will not work since “self.house” refers to the house part / model, not the new house object.