我正在努力了解元表如何工作以及为什么在Lua中需要使用元表来创建类和继承。我为Lua找到的每个OOP示例都与上一个稍有不同,但是它们始终使用元表,特别是__index属性。这是我实现一些简单继承的方法:

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()


输出:

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


据我所知,这很好。使用元表将如何改善我的设计?

最佳答案

没有人说过,OOP需要使用元表。它们很有用,不是必需的。

使用元表可以隐藏数据。我可以很容易地破坏您所有仔细的编码:

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


它还将允许其他可疑构造,例如在对象dog.newVar = foo中存储其他数据。

OOP不仅仅是继承。良好的OOP还应包含encapsulation,以维护对象的完整性,以防意外使用。通过使用主表的空表并过滤所有设置并通过__index__newindex元方法,元表允许您执行此操作。这样,只有对象可以在实际表中存储数据。除非您提供显式访问,否则只有对象可以检索它。

10-06 10:39