在Lua(5.2)中,元表用于OOP有什么用途?

在Lua(5.2)中,元表用于OOP有什么用途?,oop,class,inheritance,lua,metatable,Oop,Class,Inheritance,Lua,Metatable,我正在努力理解元表是如何工作的,以及为什么在Lua中需要它们来创建类和继承。我为Lua找到的每个OOP示例都与上一个略有不同,但它们总是使用元表,特别是对于\uu index属性。下面是我如何实现一些简单继承的: Animal = {} function Animal.New() local self = {} self.sName = "Generic Animal" self.GetName = function(self) return self.sName e

我正在努力理解元表是如何工作的,以及为什么在Lua中需要它们来创建类和继承。我为Lua找到的每个OOP示例都与上一个略有不同,但它们总是使用元表,特别是对于
\uu 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还应该包含,以维护对象的完整性,防止意外误用。元表允许您为主表使用空表,过滤所有设置并通过
\uuuu index
\uuu newindex
元方法来实现这一点。这样,只有对象才能在实际表中存储数据。除非您提供显式访问,否则只有对象才能检索它。

您是否阅读过Lua编程的第13章和第16章,它给出了我所知道的最好的解释。在线版本是5.0版的,但我认为基础还是一样的。在我的谷歌搜索中,我没有遇到过那一章(13)。这实际上对更好地理解元表非常有帮助。谢谢。嗯,我确实明白你对封装的看法,但实际上在Lua中,尽管有人尽了最大的努力,你还是无法阻止其他程序员把事情搞砸,对吗?不管您如何封装,它仍然可以像
Chihuahua=nil
一样简单。另外,我还没有机会测试它,但是尽管函数定义已经连接到了一个元表,但是你不能仍然弄乱它们吗?换句话说,
Chihuahua:GetName
是否仍然可以设置为nil,而不管它是否是元表的一部分;Lua有办法阻止甚至
Chihuahua=nil
工作。您所要做的就是锁定脚本的环境。Lua有很多方法可以做到这一点。是的,如果确定了用户,那么他们可以通过获取元表来破坏对象的封装(除非您删除
getmetatable
函数。然后他们就被套住了)。但重点不是防止恶意使用,而是防止愚蠢。简而言之,你没有理由不能这样做。