理解LUA中的多重继承
有人在问如何实现Lua中的多重继承。真正用到多重继承的时候,我会想想是不是非得用多重继承,总觉得多重继承有点“重”。
多重继承例子
|
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
47
48
49
50
51
52
|
local function search(k, tables) for i, v in ipairs(tables) do if v[k] then return v[k] end end return nilend-- 这里实现多重继承,参数arg为多重父类表function createClassFrom(...) -- c为返回值的目标表,为实现多重继承的子类表 local c = {} local parents = {...} setmetatable(c, {__index = function(t, k) return search(k, parents) end}) function c:new(o) o = o or {} setmetatable(o, {__index = c}) return o end return cend-- 人 吃饭Human = {name = "human"}function Human:eat() print("human eat")end-- 程序员 写代码Programmer = {name = "coder"}function Programmer:doProgramming() print("do coding")end-- 女程序员 继承 人和程序员-- 性别女FemaleProgrammer = createClassFrom(Human, Programmer)local femaleCoder = FemaleProgrammer:new({sex = "female", canBear = function() print("Female: can give birth a baby!") end})femaleCoder:eat() -- human eatfemaleCoder:doProgramming() -- do coding |
上面代码难点在于理解lua中__index的用法。我们在lua中实现继承的时候,会用到这个__index。我们再次看看这个__index究竟是怎么回事。元表的__index可以是一个表,也可以是一个函数。
1. __index是个表的情况
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
local Test = { group = "quick" }function Test:new(o) o = o or {} setmetatable(o, {__index = Test}) return oendfunction Test:getName() return self.nameendfunction Test:setName(name) self.name = nameendlocal a = Test:new({name = "Just a test"})print(a:getName()) -- Just a testprint(a.group) -- quick |
当表a调用自身所没有的方法( getName() )或者属性(group)的时候, Lua会通过getmetatable(a)得到a的元表{index = Test}, 而该元表的`index`是个表Test,则Lua会在这个表Test中看看是否有缺少的域方法("getName")以及属性(group),如果找到了则会调用表Test的方法或者属性。
2. __index 是函数的情况
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
local Test = { }Test.prototype = { group = "quick", qq = "284148017", company = "chukong", getName = function() return "Just a test" end}function Test:new(o) o = o or {} setmetatable(o, {__index = function(table, key) return Test.prototype[key] end}) return oendlocal a = Test:new()print(a:getName()) -- Just a testprint(a.qq) -- 284148017print(a.company) -- chukong |
当表a调用自身所没有的方法(getName)或者属性(qq/company)的时候, lua会通过getmetatable(a)得到a的元表
{__index = function(table, key) return Test.prototype[key] end}, 而该元表的__index是个函数,该函数的实参依次为正在调用方法、属性的表a以及表a中缺失的方法名或属性(键值key),lua会将这两个实参传入进去并调用__index指向的函数。
例如:
- a:getName()时,就会调用a的元表的__index方法,将自身a以及"getName"键名依次传入进去,返回了Test.prototype["getName"]该函数,lua会自动调用该函数,所以a:getName()会返回Just a test。
- a.qq时,就会调用a的元表的__index方法,将自身a以及"qq"键名依次传入进去,返回了Test.prototype["qq"]即284148017。
相关阅读
- 关于lua的单个继承,可以查看以前这篇详解QuickCocos2dX继承机制
浙公网安备 33010602011771号