user1191220
user1191220

Reputation:

how to write private function in lua class

I'm trying to write a lua "class" with a private function like this:

local myTable = {}

function myTable.func()
    private()
end

local function private()
    print(":O")
end

return myTable

Let's say I'll require myTable and then run myTable.func() I'll get an error that says private is not defined.

I've found 2 ways to solve this:

  1. move the function private in front of func

  2. Forward declare local private before func and change the signature of private to function private.

But I'm a little confused about why they are working and which is the common way.

Upvotes: 5

Views: 12474

Answers (4)

mkluwe
mkluwe

Reputation: 4061

First of all: In your code snippet it's not clear to me where the "class" is, as myTable is just an object. If you put this in a module and require it, you just get an object.

You could do something like this:

local function MyTable() -- constructor
    local function private()
        print(":O")
    end
    return {
        func = function()
            private()
        end
    }
end

local m = MyTable()
m.func()

This may not be the usual way of doing OOP in Lua, but here private obviously is .. well .. private.

Upvotes: 2

Ashura
Ashura

Reputation: 86

I created this samplecode:

local object = {}

do -- Creates Scope

    -- Private Scope

    local fire_rate = 5

    -- Public Scope

    function object:load()

    end

    function object:update()

    end

    function object:draw()

    end

    function object:setFireRate(rate)
        fire_rate = rate
    end

    function object:getFireRate()
        return fire_rate
    end
end

return object

Hope this helps.

Upvotes: 0

Creator
Creator

Reputation: 161

You'll basically need something like this:

local function Bezier(x1,y1,x2,y2,x3,y3)
--Private
local inf = 1/0
local x1 = x1
local y1 = y1
local x2 = x2
local y2 = y2
local x3 = x3
local y3 = y3

local maxY = y1 > y2 and (y1 > y3 and y1 or y3) or y2 > y3 and y2 or y3
local minY = y1 < y2 and (y1 < y3 and y1 or y3) or y2 < y3 and y2 or y3

local maxX = x1 > x2 and (x1 > x3 and x1 or x3) or x2 > x3 and x2 or x3
local minX = x1 < x2 and (x1 < x3 and x1 or x3) or x2 < x3 and x2 or x3

local xc = (x3 - 2*x2 + x1)
local xb = 2*(x2 - x1)
local yc = (y3 - 2*y2 + y1)
local yb = 2*(y2 - y1)

--Public
local self = {}

--Render
self.render = function(resolution)
    local path = {}
    local num = 1
    for index=0, 1, 1/resolution do
        path[num] = {(1-index)^2*x1+2*(1-index)*index*x2+index^2*x3, (1-index)^2*y1+2*(1-index)*index*y2+index^2*y3}
        num = num + 1
    end
    return path
end
--Point
function self.point(index)
    return {(1-index)^2*x1+2*(1-index)*index*x2+index^2*x3, (1-index)^2*y1+2*(1-index)*index*y2+index^2*y3}
end
--Get x of patricular y
function self.getX(y)
    if y > maxY or y < minY then
        return
    end
    local a = y1 - y
    if a == 0 then
        return
    end
    local b = yb
    local c = yc
    local discriminant = (b^2 - 4*a*c )

    if discriminant < 0 then
        return
    else
        local aByTwo = 2*a
        if discriminant == 0 then
            local index1 = -b/aByTwo
            if 0 < index1 and index1 < 1 then
                print("=====",y,1,maxY,minY)
                return (1-index1)^2*x1+2*(1-index1)*index1*x2+index1^2*x3
            end
        else
            local theSQRT = math.sqrt(discriminant)
            local index1, index2 = (-b -theSQRT)/aByTwo, (-b +theSQRT)/aByTwo
            if 0 < index1 and index1 < 1 then
                if 0 < index2 and index2 < 1 then
                    print("=====",y,2,maxY,minY)
                    return (1-index1)^2*x1+2*(1-index1)*index1*x2+index1^2*x3, (1-index2)^2*x1+2*(1-index2)*index2*x2+index2^2*x3
                else
                    print("=====",y,1,maxY,minY)
                    return (1-index1)^2*x1+2*(1-index1)*index1*x2+index1^2*x3
                end
            elseif 0 < index2 and index2 < 1 then
                print("=====",y,1,maxY,minY)
                return (1-index2)^2*x1+2*(1-index2)*index2*x2+index2^2*x3
            end
        end
    end     
end
--Get y of patricular x
function self.getY(x)
    if x > maxX or x < minX then
        return 
    end
    if maxX == minX and x == minX then
        return minY, maxY
    end
    local index1, index2, buffer1, buffer2
    local a = (x1 - x)
    if a == 0 then
        return
    end
    local b = xb
    local c = xc
    local discriminant = b^2 - 4*a*c 
    if discriminant < 0 then
        return
    else
        local aByTwo = 2*a
        local theSQRT = math.sqrt(discriminant)
        if discriminant == 0 then
            local index1 = -b/aByTwo
            return (1-index1)^2*y1+2*(1-index1)*index1*y2+index1^2*y3
        else
            local index1, index2 = (-b - theSQRT)/aByTwo, (-b + theSQRT)/aByTwo
            return (1-index1)^2*y1+2*(1-index1)*index1*y2+index1^2*y3, (1-index2)^2*y1+2*(1-index2)*index2*y2+index2^2*y3
        end
    end
end
--Scanline render
function self.scanRender()
    local path = {}
    local counter = 1
    local fX, sX
    local a = (y3 - 2*y2 + y1)
    local b = 2*(y2 - y1)
    for i=minY, maxY do
        fX, sX = self.getX(i,a,b)
        if fX then
            path[counter] = fX
            path[counter+1] = i
            counter = counter + 2
            if sX then
                path[counter] = sX
                path[counter+1] = i
                counter = counter + 2
            end
        end
    end
    return path
end
--More efficient
--Self
return self
end

By calling bezier, you get a Bezier object. This object will be able to access all the private attributes and the public interface that is in the self table.

Upvotes: 0

Rochet2
Rochet2

Reputation: 1156

which is the common way

Both work and both are advisable. The second approach is needed in situations where you have two functions that call each other and both need to be local but not inside a table.

You could always use the second style and thus keep consistency, though it might not be as readable as you would need to go to a different place in code to see if your function is local.

However for readability and shorter code I would use the first approach so I don't need a separate "declaration" of my local functions.

im little confused about why they are working

The reason the original code does not work is because of local variable scope. From lua reference manual:

Lua is a lexically scoped language. The scope of a local variable begins at the first statement after its declaration and lasts until the last non-void statement of the innermost block that includes the declaration.

So in your original code the variable private is defined as the function only after the line where it is defined. And the code fails because you try to use it in code that is before that line.

The approaches work because both move the local variable scope to start above the code where you use the variable.

You may want to read about local variables and the scoping in the reference manual:

Upvotes: 7

Related Questions