Question

I'm struggling to understand how metatables work and why they are needed in Lua for creating classes and for inheritance. Every OOP example I find for Lua is a little different from the last, but they always use metatables, specifically for the __index property. Here is how I implemented some simple inheritance:

Animal = {}

function Animal.New()
  local self = {}
  self.sName = "Generic Animal"

  self.GetName = function(self)
    return self.sName
  end

  self.Speak = function(self)
    -- Do nothing, abstract function
  end

  return self
end

Dog = {}

function Dog.New()
  local self = Animal.New()
  self.sName = "Dog"

  self.Speak = function(self)
    print("Bark!")
  end

  return self
end

Labrador = {}

function Labrador.New()
  local self = Dog.New()
  self.sName = "Labrador"
  return self
end

Chihuahua = {}

function Chihuahua.New()
  local self = Dog.New()
  self.sName = "Chihuahua"

  self.Speak = function(self)
    print("Yap yap!")
  end

  return self
end

-- Test --

l = Labrador.New()
print(l:GetName())
l:Speak()

c = Chihuahua.New()
print(c:GetName())
c:Speak()

d = Dog.New()
print(d:GetName())
d:Speak()

a = Animal.New()
print(a:GetName())
a:Speak()

Output:

Labrador
Bark!
Chihuahua
Yap yap!
Dog
Bark!
Generic Animal

So as far as I can see, this works just fine. How would using metatables improve my design?

Was it helpful?

Solution

Nobody says that metatables are needed for OOP. They're useful, not essential.

Metatables allow you to hide data. I can break all of your careful coding very easily:

local dog = Chihuahua.New()
dog.sName = nil --Oops.
dog.GetName = nil --Oops.

It would also allow other dubious constructs, such as storing other data in the object: dog.newVar = foo.

OOP is about more than just inheritance. Good OOP should also incorporate encapsulation, to maintain the integrity of an object from accidental misuse. Metatables allow you to do this by using an empty table for the main table and filtering all setting and getting through __index and __newindex metamethods. This way, only the object can store data in the actual table. And only the object can retrieve it unless you provide explicit access.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top