Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
2

How to make an objects variables private?

Asked by 8 years ago

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?

0
What do you mean by, 'make an objects' variable private', exactly? TheeDeathCaster 2368 — 8y
0
often in some coding languages you can declare something private or public. This determines if the public or private item can be used by foreign scripts or objects that are implementing the object. Public gives access, while private does not randomsmileyface 375 — 8y

2 answers

Log in to vote
2
Answered by 8 years ago

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
0
It works perfectly! But its really biting me, how does slices and toppings stay around? randomsmileyface 375 — 8y
0
local variables don't get garbage collected until everything that uses them no longer exists, so as long as pizza exists, those local variables will exist as well. EchoReaper 290 — 8y
Ad
Log in to vote
0
Answered by
drahsid5 250 Moderation Voter
8 years ago

'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.

0
...I'm not sure if this flew past you, but your first example is entirely wrong, and how you edited my code does nothing to make "Slices" private randomsmileyface 375 — 8y
0
But I get the concept anyways... I was explained it on another site. I guess thanks randomsmileyface 375 — 8y
1
This doesn't answer the question at all -- `Slices` is still very much "public". BlueTaslem 18071 — 8y
0
Huh? My bad. drahsid5 250 — 8y

Answer this question