今天看到咱们quick群里有人在问如何实现多重继承,想想自己好像还真没用过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
| local function search(k, tables) for i, v in ipairs(tables) do if v[k] then return v[k] end end return nil end
function createClassFrom(...) 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 c end
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() femaleCoder:doProgramming()
|
上面代码难点在于理解lua中__index
的用法。我们在lua中实现继承的时候,会用到这个__index
。我们再次看看这个__index
究竟是怎么回事。元表的__index
可以是一个表,也可以是一个函数。
1. __index是个表的情况
__index是个表的情况1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| local Test = { group = "quick" } function Test:new(o) o = o or {} setmetatable(o, {__index = Test}) return o end
function Test:getName() return self.name end
function Test:setName(name) self.name = name end
local a = Test:new({name = "Just a test"}) print(a:getName()) print(a.group)
|
当表a调用自身所没有的方法( getName() )或者属性(group)的时候, lua会通过getmetatable(a)得到a的元表{index = Test}, 而该元表的`index`是个表Test,则lua会在这个表Test中看看是否有缺少的域方法(“getName”)以及属性(group),如果找到了则会调用表Test的方法或者属性。
2. __index 是函数的情况
__index 是函数的情况1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 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 o end
local a = Test:new() print(a:getName()) print(a.qq) print(a.company)
|
当表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
。
相关阅读
最后
如果代码有问题或者其他疑问,欢迎一起探讨学习
Happy Coding:)