【问题标题】:how to write private function in lua class如何在lua类中编写私有函数
【发布时间】:2021-11-30 03:40:45
【问题描述】:

我正在尝试使用这样的私有函数编写一个 lua“类”:

local myTable = {}

function myTable.func()
    private()
end

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

return myTable

假设我需要 myTable 然后运行 ​​myTable.func() 我会收到一条错误消息,指出 private 未定义。

我找到了两种解决方法:

  1. 将函数private移到func前面

  2. func之前转发声明local private并将private的签名更改为function private

但我对它们为什么起作用以及常用方式有点困惑。

【问题讨论】:

  • @Rochet2 给出了一个很好的答案。还可能知道local“声明”了一个新的本地变量(它可以随时保存任何类型的任何一个值);而且,函数是在运行时计算函数定义表达式时创建的值,函数没有签名。
  • 当我想弄清楚如何在Lua中做一些与OOP相关的事情时,我通常将基本代码写在Moonscript中。 Moonscript 将代码编译成 Lua - 所以你可以看到底层代码的样子。
  • 问题只是当你定义方法时它没有找到值,因为它之前没有在本地定义。该方法正在寻找一个全局变量。

标签: lua


【解决方案1】:

这是常见的方式

建议两者都有效。在您有两个相互调用的函数并且都需要在本地但不在表内的情况下,需要使用第二种方法。

可以始终使用第二种样式,从而保持一致性,尽管它可能不像您需要转到代码中的不同位置以查看您的函数是否是本地的那样可读。

但是为了可读性和更短的代码我会使用第一种方法,因此我不需要单独“声明”我的本地函数。

我对他们为什么工作有点困惑

原始代码不起作用的原因是局部变量范围。 来自 lua 参考手册:

Lua 是一种词法作用域语言。 局部变量的作用域 从声明后的第一个语句开始,一直持续到 包含 声明。

因此,在您的原始代码中,变量private 仅在定义它的行之后 被定义为函数。并且代码失败是因为您尝试在该行之前的代码中使用它。

这些方法之所以有效,是因为两者都将局部变量范围移动到您使用该变量的代码之上。

您可能想阅读参考手册中的局部变量和范围:

【讨论】:

    【解决方案2】:

    首先:在您的代码 sn-p 中,我不清楚“类”在哪里,因为 myTable 只是一个对象。如果你把它放在一个模块中并require 它,你就会得到一个对象。

    可以做这样的事情:

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

    这可能不是在 Lua 中进行 OOP 的常用方式,但这里 private 显然是 .. 好吧 .. 私有的。

    【讨论】:

      【解决方案3】:

      我创建了这个示例代码:

      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
      

      希望这会有所帮助。

      【讨论】:

        【解决方案4】:

        你基本上需要这样的东西:

        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
        

        通过调用 bezier,你会得到一个 Bezier 对象。该对象将能够访问 self 表中的所有私有属性和公共接口。

        【讨论】:

        • 不要介意代码本身,这是我的另一个项目。
        猜你喜欢
        • 2018-04-21
        • 1970-01-01
        • 2016-09-25
        • 2019-10-17
        • 1970-01-01
        • 2012-10-01
        • 2021-09-13
        • 2021-02-18
        • 2022-01-27
        相关资源
        最近更新 更多