这两个Lua示例之间有什么区别?一个更好吗?

Jef*_*man 5 lua

我刚刚开始使用Lua.在我正在学习的例子中(Ghosts&Monsters Corona开源),我反复看到这种模式.

local director = require("director")

local mainGroup = display.newGroup()

local function main()

   mainGroup:insert(director.directorView)

   openfeint = require ("openfeint")
   openfeint.init( "App Key Here", "App Secret Here", "Ghosts vs. Monsters", "App ID Here" )

   director:changeScene( "loadmainmenu" )

   return true
end

main()
Run Code Online (Sandbox Code Playgroud)

这是Lua程序员推荐的某种惯例,或者这样做是否有真正的优势?为什么你不能一起跳过这个功能并执行此操作:

local director = require("director")

local mainGroup = display.newGroup()

mainGroup:insert(director.directorView)

local openfeint = require ("openfeint")
openfeint.init( "App Key Here", "App Secret Here", "Ghosts vs. Monsters", "App ID Here" )

director:changeScene( "loadmainmenu" )
Run Code Online (Sandbox Code Playgroud)

第二种风格对第一种风格有一些隐含的好处吗?谢谢!

Mud*_*Mud 8

这是Lua程序员推荐的某种惯例,或者这样做是否有真正的优势?

这不典型.优点是对象状态是私有的,但这并不足以推荐它.

我反复看到这种模式.

我以前从未见过它,它只在您发布的源中发生过一次.

编辑:在本帖子下面的评论中添加对问题的回复.

访问外部局部变量的函数绑定到那些变量,称为"闭包".Lua(由于历史原因)将那些绑定变量称为"upvalues".例如:

local function counter()
   local i = 1
   return function()
      print(i)
      i = i + 1
   end
end

local a, b = counter(), counter()
a() a() a() b() --> 1 2 3 1
Run Code Online (Sandbox Code Playgroud)

a并且从输出中可以看到b绑定到不同副本的闭包i.换句话说,您可以将闭包视为具有自身私有状态的函数.您可以使用它来模拟对象:

function Point(x,y)
   local p = {}
   function p.getX() -- syntax sugar for p.getX = function()
      return x
   end
   function p.setX(x_)
      x = x_
   end
   -- for brevity, not implementing a setter/getter for y
   return p
end

p1 = Point(10,20)
p1.setX(50)
print(p1.getX())
Run Code Online (Sandbox Code Playgroud)

Point返回一个闭包表,每个闭包都绑定到本地xy.该表不包含点的状态,闭包本身通过它们的upvalues.重要的一点是,每次Point调用它都会创建新的闭包,如果你有大量的对象,效率不是很高.

在Lua中创建类的另一种方法是创建将表作为第一个参数的函数,其中状态存储在表中:

function Point(x,y)
   local p = {x=x,y=y}
   function p:getX() -- syntax sugar for p.getX = function(self)
      return self.x
   end
   function p:setX(x)
      self.x = x
   end
   return p
end

p1 = Point(10,20)
p1:setX(50) -- syntax sugar for p1.setX(p1, 50)
print(p1:getX()) -- syntax sugar for p1.getX(p1)
Run Code Online (Sandbox Code Playgroud)

到目前为止,我们仍然在创建每个方法的新副本,但是现在我们不依赖于upvalues for state,我们可以解决这个问题:

PointClass = {}
function PointClass:getX() return self.x end
function PointClass:setX(x) self.x = x end
function Point(x,y)
   return {
      x = x,
      y = y,
      getX = PointClass.getX,
      setX = PointClass.getY,
   }
end
Run Code Online (Sandbox Code Playgroud)

现在,方法创建一次,并且所有Point实例共享相同的闭包.更好的方法是使用Lua的元编程工具使新Point实例自动查找PointClass实例本身中找不到的方法:

PointClass = {}
PointClass.__index = PointClass -- metamethod
function PointClass:getX() return self.x end
function PointClass:setX(x) self.x = x end
function Point(x,y)
   return setmetatable({x=x,y=y}, PointClass)
end

p1 = Point(10,20)
-- the p1 table does not itself contain a setX member, but p1 has a metatable, so 
-- when an indexing operation fails, Lua will look in the metatable for an __index
-- metamethod. If that metamethod is a table, Lua will look for getX in that table,
-- resolving p1.setX to PointClass.setX.
p1:setX(50)
Run Code Online (Sandbox Code Playgroud)

这是在Lua中创建类的更惯用的方式.它的内存效率更高,更灵活(特别是它可以轻松实现继承).