1.继承

1.1 关键字Class

使用Class关键字来继承是规范的做法

不用担心父类的方法无法访问

甚至貌似可以不用设置元表和__index

local TestBaseClass = class("TestBaseClass")

local TestExtendClass = class("TestExtendClass" , TestBaseClass)

实例化类的对象可以用new方法

local t = TestExtendClass.new()

 

1.2 关键字super

local ext = TestExtendClass.new()

print("ext start")
ext.super.Fun1(ext)
ext:Fun1()
print("ext" , ext.super.val)
print("ext" , ext.val)

 

[LUA-print] ext start
[LUA-print] TestBaseClass.Fun1 val_of_TestBaseClass
[LUA-print] TestExtendClass.Fun1 val_of_TestExtendClass
[LUA-print] ext val_of_TestBaseClass
[LUA-print] ext val_of_TestExtendClass

 

可见,父类中的方法和属性,都可以通过super访问到

 

1.3 getmetatable

local p = {}

这时getmetatable(p)返回nil

local p= class("p")

这时getmetatable(p)返回一个table

可以理解为class关键字更规范的定义了类

类有new方法,但普通对象则没有

 

1.4 setmetatable

local TempBase = {
b = "TempBase_b"
}
local TempClass = {
a = "Aa"
}

setmetatable(TempClass , {
__index = TempBase
})

print("TempClass" , TempClass.a)
print("TempClass" , TempClass.b)

 

[LUA-print] TempClass Aa
[LUA-print] TempClass TempBase_b

 

对象也可以使用继承

更准备的理解是扩展这个对象本身

若对象x继承自对象a,则必须使用语法

setmetatable(x, {
__index = a
})

若对象x继承自类A,则可以像上面那样写

也可以简单写做setmetatable(x, A)

继承是可以层层传递的

 

1.5 __metatable

在Lua中,函数setmetatable和getmetatable函数会用到元表中的一个字段,用于保护元表,该字段是__metatable。当我们想要保护集合的元表,是用户既不能看也不能修改集合的元表,那么就需要使用__metatable字段了;当设置了该字段时,getmetatable就会返回这个字段的值,而setmetatable则会引发一个错误;如以下演示代码:

function Set.new(l)
    local set = {}
     setmetatable(set, mt)
    for _, v in pairs(l) do set[v] = true end
     mt.__metatable = "You cannot get the metatable" -- 设置完我的元表以后,不让其他人再设置
     return set
end

local tb = Set.new({1, 2})
print(tb)

print(getmetatable(tb))
setmetatable(tb, {})

上述代码就会打印以下内容:
{1, 2}
You cannot get the metatable
lua: test.lua:56: cannot change a protected metatable

1.6 __index

使用class关键字继承的情况下,似乎完全不需要处理__index元方法

其描述如下

当访问一个table的字段时,如果table有这个字段,则直接返回对应的值;
当table没有这个字段,则会促使解释器去查找一个叫__index的元方法,接下来就就会调用对应的元方法,返回元方法返回的值;
如果没有这个元方法,那么就返回nil结果。

可以用__index为对象赋上 默认 属性/方法集合

因为Lua以table和"不存在key"作为参数来调用该函数,所以若访问的是"存在的key",则不会使用默认值

__index原方法是metatable中的一个元方法,并不是直接在对象上

参考http://www.jellythink.com/archives/511