K.Moore
K.Moore

Reputation: 23

bad argument #2 to 'setmetatable' (nil or table expected)?

I currently stuck on this with a corona app I'm creating.

I have a file structure like below: App -> Classes -> Objects -> Ships

In the App folder is the main.lua, menu.lua, level.lua and Class.lua. In the Classes folder there is Object.lua. In Objects, ship.lua and finally in the Ships are my different ships i.e. player and enemy.

I followed this tutorial and my code is almost completely identical to his (bar player and enemys classes), but still am receiving this error in the Class.lua is

"bad argument #2 to 'setetatable'(nil or table expected)"

The code I receive the error on is

function Class(Super)
  Super = Super or Base
  local prototype = setmetatable({}, Super) -- receive error here
  prototype.class = prototype
  prototype.super = Super
  prototype.__index = prototype
  return prototype
end

Base = Class()

function Base:new(...)
  local instance = setmetatable({}, self)
  instance:initialize(...)
  return instance
end

function Base:initialize() end

function Base:get()
  local Instances = self.Instances
  if (not Instances[1]) then local obj = self:new() end
  return table.remove(Instances, 1)
end

function Base:dispose()
  table.insert(self.Instances, self)
end

I've tried changing the classes and changing the "setmetatable({},Super)" to "setmetatable(Super, self), putting all the classes in one file, I've read the lua docs, requiring the Class.lua in the mai, menu and the level.lua etc. and nothing has worked.

Any help would be greatly appreciated.

Thanks

Upvotes: 2

Views: 2011

Answers (1)

Etan Reisner
Etan Reisner

Reputation: 80941

function Class(Super)
  Super = Super or Base
  local prototype = setmetatable({}, Super) -- receive error here
  prototype.class = prototype
  prototype.super = Super
  prototype.__index = prototype
  return prototype
end

Base = Class()

Follow the execution of the code above.

You declare a function Class and then call it (and assign its returned value to Base).

Step through the execution of Class from the Base = Class() line.

function Class(Super)

The function takes one argument named Super

Super = Super or Base

You are allowing the Super argument to be nil/unpassed by using a default value of Base. This call Base = Class() is not passing a value so this line Super = Super or Base has Super as nil and so evaluates to Super = nil or Base however the global Base is also nil as it has not yet been assigned to so you get Super = nil.

local prototype = setmetatable({}, Super)

This line then attempts to use Super (assigned from the line before) only it is, as we just saw, nil hence your error.

The bit from the tutorial that you missed (or at least missed in your posted snippet) is the crucially important local Base line above the Class function definition.

Upvotes: 2

Related Questions