为什么它是同一张桌子,即使它不是原型

时间:2017-01-22 03:19:46

标签: lua closures factory-method

我有这段代码:

function createRect(x, y, w, h)
  local rect = {
    type = "rect",
    x = x,
    y = y,
    w = w,
    h = h,
    translate = function(rect, vector)
      assert(vector.type == "vector2d")
      local rect = shapes.createRect(rect.x + vector.x, rect.y + vector.y, rect.w, rect.h)
    end,
  }

  return rect
end

translate = function(rect, vector)
  assert(vector.type == "vector2d")
  local rect = shapes.createRect(rect.x + vector.x, rect.y + vector.y, rect.w, rect.h)
end

local o = createRect(2,3,4,5)
local q = createRect(2,3,4,5)

print(o.translate, q.translate, translate)

这是一些非常简单的代码,用于测试Lua中的测试工厂函数,非常让人联想到JS模块模式。在谈论工厂功能时,人们通常会抱怨的是内存占用。 由于oq刚刚分配,因此我们假设它们具有不同的translate()函数。 但事实证明我错了:

function: 0x7fcdbe600d50        function: 0x7fcdbe600d50        function: 0x7fcdbe600d90 

这是为什么?怎么会这样呢?我假设o.translateq.translate是不同的功能,但它们是相同的......

1 个答案:

答案 0 :(得分:5)

  

这怎么可能呢?我假设o.translateq.translate是不同的功能,但它们是相同的......

通常你是对的,但是Lua 5.2引入了一个优化,如果满足某些条件,可以缓存匿名函数。具体来说,如果它引用的值在构造之间没有变化,那么该匿名函数的第一个创建实例将被重用。

repl.it,Lua 5.1中运行您的示例,将其显示为一个可能的输出:

function: 0xb81f30  function: 0xb81f00  function: 0xb82ca0

但是在melpon.org/wandbox下运行它,Lua 5.2+,显示:

function: 0x14f0650 function: 0x14f0650 function: 0x14efb40

在您的示例中,createRect为每个调用创建并返回不同的rect表,但由于此优化,字段rect.translate被分配了与lua值相同的匿名函数。

另见