喜欢2D(Lua)意想不到的对象

时间:2017-08-21 16:18:55

标签: lua love2d

尝试用LUA和Love2D弄湿我的脚,我在Lua中遇到了对象实例化/访问的问题。

可以在此处找到有错误的来源:https://bitbucket.org/dannsee/love_scrollingshooter

我在我的主力,我创造了一个物体,敌人

enemies = Enemies:new()

并且在敌人对象内部,我创建了一个对象来保存peristant值,我称之为Timers。

timers = Timers:new()

所以敌人'构造函数'方法看起来(基本上)就像这样

Enemies = {} -- so that Enemies will not be nil when new() is called
timers = {} -- so that timers will be accessible in the class scope

function Enemies:new(enemies)
  enemies = enemies or {}
  timers = Timers:new()
  setmetatable(enemies, self)
  self.__index = self
  return enemies
end

正在创建的计时器看起来像这样

Timers = {} -- so that Timers will not be nil when new() is called

function Timers:new(timers)
    timers = timers or {
      miniBombTimerMax = 0.2,
      miniBombTimer = minibombTimerMax
    } 
    setmetatable(timers, self)
    self.__index = self
    return timers
end

但是当我尝试引用其中一个计时器(来自敌人对象内部)时,我得到一个零值异常。

timers.miniBombTimer -- Produces nil exception

在我看来,这应该是1.在范围内,因为它是在这个类中创建的对象,并且在为其分配值之前在本地实例化为timers = {},并且2.不是nil因为它正在'构造函数'中给出一个值。但似乎有更多的事情在这里,我没有抓住。

我是Lua的新手,在这一点上可能是显而易见的,但从我读到的有关变量范围的内容看来,这应该是有效的。我不明白为什么定时器不是用值创建的。

1 个答案:

答案 0 :(得分:0)

小心你的全局!在Lua中,当你不想要的时候,很容易意外地设置一个全局变量,看起来这就是正在发生的事情。

function Enemies:new(enemies)
  enemies = enemies or {}
  timers = Timers:new()
  setmetatable(enemies, self)
  self.__index = self
  return enemies
end

在这里的第三行,由于此处timers不存在作为局部变量,因此该值最终会被放入名为timers全局变量中。如果您要设置enemies的属性,则需要明确提及enemies

function Enemies:new(enemies)
  enemies = enemies or {}
  enemies.timers = Timers:new()
  setmetatable(enemies, self)
  self.__index = self
  return enemies
end

现在,你写道:

  

但是当我尝试引用其中一个计时器(来自敌人对象)时,我得到一个零值异常。

Lua并没有任何“在一个对象内”或“一个类内”的概念。在某些语言中,当您在类中编写代码时,所有类的成员都在范围内,您可以“裸”引用它们。 Lua不是那些语言之一;在Lua中,如果要引用“类成员”,则需要使用点表示法,明确说明您正在访问哪个对象。 (或者您可以使用_ENV执行“高级方法”。)

顺便说一句......

timers = {} -- so that timers will be accessible in the class scope

从我在问题中看到的情况来看,这条线并没有太大作用;它只是创建一个从未使用的全局变量。

此外,Enemies:new中的这一行:

self.__index = self

每次调用Enemies.__index时,这只会设置Enemies:new。这是罚款,但您也可以只设置一次:

function Enemies:new(enemies)
  enemies = enemies or {}
  enemies.timers = Timers:new()
  setmetatable(enemies, self)
  return enemies
end

Enemies.__index = Enemies