关注小众语言、AI技术,记录、分享技术点滴!

0%

lua利用metatable实现类的继承和多态

在lua原生语法特性中是不具备面向对象设计的特性。因此,要想在lua上像其他高级语言一样使用面向对象的设计方法,就需要使用原生的元表(metatable)来模拟面向对象设计。

一、元表setmetatable
对指定 table 设置元表(metatable),如果元表(metatable)中存在__metatable键值,setmetatable会失败。

以下实例演示了如何对指定的表设置元表:

1
2
3
mytable = {}                          -- 普通表
mymetatable = {} -- 元表
setmetatable(mytable,mymetatable) -- 把 mymetatable 设为 mytable 的元表

二、元表__index 元方法
这是 metatable 最常用的键。
当你通过键来访问 table 的时候,如果这个键没有值,那么Lua就会寻找该table的metatable(假定有metatable)中的_index 键。如果_index包含一个表格,Lua会在表格中查找相应的键。

1
2
3
4
5
6
other = { foo = 3 }
t = setmetatable({}, { __index = other })
print(t.foo)
3
print(t.bar)
nil

三、使用metatable实现继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
local _M = {
version = 'lua 1.0'
}

local parent = {
__index = _M
}

function parent.new()
-- 初始化new,如果没有这句,那么类所建立的对象如果有一个改变,其他对象都会改变
local new = {}
-- 使用setmetatable来实现继承
setmetatable(new, parent)
return new
end

function _M:echo()
print("M:echo "..self.version)
end

四、使用metatable实现重载和多态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
local _M = {
version = 'lua 1.0'
}

local parent = {
__index = _M
}

function parent.new()
-- 初始化new,如果没有这句,那么类所建立的对象如果有一个改变,其他对象都会改变
local new = {}
-- 使用setmetatable来实现继承
setmetatable(new, parent)
return new
end

function _M:echo()
print("M:echo "..self.version)
end


local _M2 = parent.new()

local child = {
__index = _M2
}

function child.new()
-- 初始化new,如果没有这句,那么类所建立的对象如果有一个改变,其他对象都会改变
local new = {}
-- 使用setmetatable来实现继承
setmetatable(new, child)
return new
end

-- 重载echo方法
function _M2:echo()
print("M2:echo "..self.version)
end


test = parent.new()
test:echo()

test = child.new()
test:echo()