Lua中的子类构造函数方法

时间:2016-10-12 17:34:17

标签: inheritance lua lua-table

在Lua中掌握继承(和元数据)的概念有点困难。官方教程没有具体解释如何为子类创建构造函数。

我的示例问题是player:move()nil,因此播放器仍然是Object

-- Generic class
Object = {}
function Object:new (type,id,name)
    o = {}
    self.type = type or "none"
    self.id = id or 0
    self.name = name or "noname"
    setmetatable(o, self)
    self.__index = self
    return o
end

function Object:place(x,y)
    self.x = x
    self.y = y
end

-- Player class
Player = Object:new()

function Player:new(id,name)
    o = Object:new("player",id,name)
    o.inventory = {}
    o.collisions = {}
    return o
end

function Player:move(x,y)
    return print("moved to " ..x.." x " .. y)
end

local player = Player:new(1, "plyr1")
player:move(2,2)

2 个答案:

答案 0 :(得分:3)

在构造函数Player:new中,我们通过以下行返回Object类的对象:

o = Object:new("player",id,name)

删除后,player:move()将被调用:

moved to 2 x 2

原因是,即使我们正在调用Player:new构造函数,我们实际上返回的是Object类的实例。在这种情况下,o属于继承属性。

答案 1 :(得分:3)

类继承的示例

通用课程

Object = {}

function Object:__tostring()
   if rawget(self, "type") then  -- only classes have field "type"
      return "Class: "..tostring(self.type)
   else                          -- instances of classes do not have field "type"
      return 
         "Type: "..tostring(self.type)..", id: "..tostring(self.id)
         ..", name: "..tostring(self.name)
   end
end

function Object:newChildClass(type)  -- constructor of subclass
   self.__index = self
   return
      setmetatable({
         type = type or "none",
         parentClass = self,
         __tostring = self.__tostring
      }, self)
end

function Object:new(id, name)        -- constructor of instance
   self.__index = self
   return
      setmetatable({
         id = id or 0,
         name = name or "noname"
      }, self)
end

function Object:place(x,y)
   self.x = x
   self.y = y
end

玩家类

Player = Object:newChildClass("player")

function Player:new(id,name)
  local o = Player.parentClass.new(self, id, name)  -- call inherited constructor
  o.inventory = {}
  o.collisions = {}
  return o
end

function Player:move(x, y)
   self:place(x, y)
   print("moved to (" ..self.x..", " .. self.y..")")
end

local player = Player:new(1, "plyr1")
print(player)     -->  Type: player, id: 1, name: plyr1
player:move(2,2)  -->  moved to (2, 2)

如何创建子类并调用继承的方法

Dog = Player:newChildClass("dog")

--- we want to override method "move" in class "dog"
function Dog:move(x, y)
   Dog.parentClass.move(self, x, y)  -- call inherited method "move"
   print("Woof!")   -- dog says "woof" after every move
end

local dog = Dog:new(42, "dg42")
print(dog)       -->  Type: dog, id: 42, name: dg42
dog:move(3,4)    -->  moved to (3, 4)
                 -->  Woof!