简体   繁体   中英

How does classed based inheritance work in Lua?

I've been reading the Lua textbook about inheritance but I'm not quite understanding how to implement it. Say I have these two classes:

Hero = {}

function Hero.new(n)
  local self = {name = n, health = 100}

  local dealDamage = function(self)
    return 10
  end

  local takeDamage = function(self, h)
    self.health = self.health - h
  end

  local getHealth = function(self, h)
    self.health = self.health + h
  end

  local getName = function(self)
    return self.name
  end

  local isDead = function(self)
    if self.health <= 0 then
      return true
    end
  return false
  end

   local __tostring = function(self) 
    return "Hero[Name: "..self.name..", health: "..self.health.."]" 
  end

  local mt = {
    __tostring = __tostring
  }
  return setmetatable({
    name = self.name,
    health = self.health,
    dealDamage = dealDamage,
    takeDamage = takeDamage,
    getHealth = getHealth,
    getName = getName,
    isDead = isDead
  }, mt)
end
return Hero

And

heroClass = require "hero"
Fighter = {}

function Fighter.new(hero)
  local self = {strength = 3}

  local beserk = function(health)
    damage = heath * 0.33
    health = health - (health * 0.25
    return damage
  end

  local __tostring = function(self) 
    return "Fighter[Name: "..name..", health: "..health.."]" 
  end

  local mt = {
    __tostring = __tostring
  }
  return setmetatable({
      strength = self.strength,
    }, mt)
end

return Fighter

What I think I'm doing wrong is how the classes are structured with the metatables. Using examples like this or a couple of other SO questions I can see that our classes are very different.

How do you properly set up inheritance where the Fighter class would inherit the function and data fields of the Hero class?

There are many different ways of defining classes in Lua. Instead of choosing some OOP system as the "proper" way, let's look at what you have and try to define how your system should work.

Your Hero class defines a constructor which returns an object where all methods and instance variables are included directly on that object. This is a pretty simple concept. The only major change I would make is to remove the self variable from the top, because you don't really use it:

function Hero.new(name)
  local dealDamage = function(self)
    return 10
  end

  local takeDamage = function(self, h)
    self.health = self.health - h
  end

  local getHealth = function(self, h)
    self.health = self.health + h
  end

  local getName = function(self)
    return self.name
  end

  local isDead = function(self)
    return self.health <= 0
  end

  local __tostring = function(self) 
    return "Hero[Name: "..self.name..", health: "..self.health.."]" 
  end

  local mt = {
    __tostring = __tostring
  }
  return setmetatable({
    name = name,
    health = 100,
    dealDamage = dealDamage,
    takeDamage = takeDamage,
    getHealth = getHealth,
    getName = getName,
    isDead = isDead
  }, mt)
end

For your Fighter class, we can create a base instance from Hero , and inherit from it using __index . (I deleted the berserk function, because it's unused. Feel free to adapt it to this code.):

-- We need the same parameter as Hero.
function Fighter.new(name)
  -- Create a base object by instantiating Hero.
  local hero = heroClass.new(name)

  local __tostring = function(self) 
    return "Fighter[Name: "..self.name..", health: "..self.health.."]" 
  end

  local mt = {
    __tostring = __tostring,
    -- Inherit from the base object.
    __index = hero,
  }
  return setmetatable({
      strength = 3,
  }, mt)
end

The advantages of this system are:

  1. Less indirection than most systems. You can just look at the object for methods instead of looking up a class table.

  2. Inheritance is flexible. You can change how it works by modifying the constructor. You could copy methods instead of using __index , or you could implement multiple inheritance, right there in your constructor!

I leave the disadvantages of this system as an exercise to the reader.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM