Hey, I'm trying my hand at Object Oriented programming. Compared to java, I'm really having a hard time making the members of an object private, and some functions public.
Here is my code. It is in a ModuleScript
local Pizza = {} function Pizza.new(...) return setmetatable({ Slices = 8; Toppings = {...}; Cooked = false; }, Pizza) end Pizza.__index = Pizza function Pizza:eat(x) if x ~= nil then self.Slices = self.Slices - x; else self.Slices = self.Slices - 1; end end function Pizza:addTopping(x) table.insert(self.Toppings, x); end Pizza.__newindex = function() error("Pizza object is private"); end return Pizza
And this is what I use to test it
pepperoni = Pizza.new("Pepperoni"); print(pepperoni.Slices); pepperoni.Slices = 2; print(pepperoni.Slices); pepperoni.cheese = 5;
Problem is, setting pepperoni.Slices will indeed change the value of Pepperoni.Slices. How in the world do I make the variable Slices private, so it can't be changed, and my data is protected?
The easiest thing to do without having to mess with metatables is to just keep the variables outside of the object. I know this goes against everything you learned about OOP, but it's what works the best in Lua, which isn't OOP. Example:
local Pizza = {} function Pizza.new(...) local slices = 8 local toppings = {...} local pizza = {} function pizza:eat(x) local originalSlices = slices if slices > 0 then slices = math.max(0, slices - (x or 1)) end return originalSlices - slices--returns slices eaten end --[[ What are you trying to access pizza.slices directly for? That's the exact opposite of what OOP is. In OOP languages, you'll always see x = pizza.GetX() instead of x = pizza.x. ]] function pizza:getSlices() return slices end function pizza:addTopping(toping) table.insert(topings, toping) end return pizza end return Pizza
'local' is the same thing as making a private value in Java.
So
local cake = 10 do print(cake) end
Output:
nil
In Lua values are local to the scope of code that they're in. So creating a value outside of a scope will make it not exist in said scope. If you don't put "local" behind the value name then it is a public value.
In your case, your code should look like this:
do local Pizza = {} function Pizza.new(...) return setmetatable({ Slices = 8; Toppings = {...}; Cooked = false; }, Pizza) end Pizza.__index = Pizza function Pizza:eat(x) if x ~= nil then self.Slices = self.Slices - x; else self.Slices = self.Slices - 1; end end function Pizza:addTopping(x) table.insert(self.Toppings, x); end Pizza.__newindex = function() error("Pizza object is private"); end return Pizza end ---- --This is outside of the scope, it will return a error. pepperoni = Pizza.new("Pepperoni"); print(pepperoni.Slices); pepperoni.Slices = 2; print(pepperoni.Slices); pepperoni.cheese = 5;
Though your problem is irrelevant: if you want your data to be protected just turn on FilteringEnabled.