lua的元表以及多继承

最近做开发的时候,有个类想要继承自多个类,虽然这种情况基本说很少(好像也不少),但还是说一下如何在lua里实现多继承。
其实很简单,首先要了解lua元表,以及lua类的实现方法。

lua元表

用lua的人都知道lua的table的强大,table有一套hashmap的查找机制,如果访问一个表中并不存在的字段,不会立即返回nil,而是先触发一套查找机制,也是我们用以实现面向对象的方法
简单的描述:元表就是用于查找的备用表。
比如:

local me = {}
print(me.money) -- me中没有money字段,所以打印出来的会是nil

这里的执行结果很明显会是nil,没有疑问(因为我是个穷逼。
但是如果我设置了元表:

local fathermayun = {
    money = 13000000000
}
local me = {}
setmetatable(me, fathermayun)
print(me.money)

这里的执行结果是!!!!!!!
nil
为什么我没有拿到马云爸爸的钱?因为没有设置__index

__index

简单的描述:是当table中一个元素不存在的时候,会触发寻找元表的__index元方法,如果不存在,则返回nil,如果存在,则返回结果。
所以,把上述代码改成

local fathermayun = {
    money = 13000000000
}
fathermayun.__index = fathermayun
local me = {}
setmetatable(me, fathermayun)
print(me.money)

这里的执行结果将是13000000000,我终于有钱了:)
上面的执行过程是:
访问me.money->发现没有这个字段->me有元表->查找元表fathermayun->lua不会直接找fathermayun里的money字段->lua发现fathermayun有元方法__index->调用元方法->发现元方法是个table,在元方法的table里寻找->获得money的值
__index有以下取值

表,会直接在表里找
函数,返回函数的返回值

继承

利用上述知识随手写了个实现面向对象的方法,不是很完善

local function class(super)
    local cls
    if super then
        cls = {}
        cls.super = super
        setmetatable(cls, {__index = super})
    else
        -- ctor是构造函数的命名
        cls = {ctor = function () end}
    end

    cls.__index = cls
    function cls.new(...)
        local instance = setmetatable({}, cls)
        instance:ctor(...)
        return instance
    end
    return cls
end

挺简单的,注释就不写了……让我们来测试一下

local Test = class()
function Test:doSomething()
    print("test doSomething")
end
local test = Test.new()
test:doSomething()

成功打印出"test doSomething"
接下来试试继承

local Test = class()
function Test:doSomething()
    print("test doSomething")
end
local Test2 = class(Test)
local test = Test2.new()
test:doSomething()

也可以成功打印出"test doSomething",继承成功
为什么能继承成功?原因如下:

在new的时候,创建一个table并返回,即创建一个实例,实例可以有自己的字段,比如Test类的doSomething,该字段是个函数,可以调用执行。实例的元表是cls,如果调用实例没有的字段,会去cls里找
cls设置了元方法__index = cls
如果没有super,则只有一个构造函数方法
如果有super,cls的元表是super,元表的元方法也正确的设置了
所以,在Test2是继承自Test的,它的实例test调用doSomething,找不到,去元表里找,元表发现自己有父类,去父类里找,成功找到。

多继承

如果我想要继承多个父类,怎么办?
其实思路很简单,把元方法改成函数即可。
举例子:

local function search(key, tables)
    for _, super in ipairs(tables) do
        if super[key] then
            return super[key]
        end
    end
    return nil
end

local function class(...)
    local cls = { ctor = function () end}
    local supers = {...}
    setmetatable(cls, {__index = function (_, key)
        -- 在查找table的时候,会把table的key传进来
        return search(key, supers)
    end})
    
    function cls.new(...)
        local instance = {}
        setmetatable(instance, {__index = cls})
        instance:ctor(...)
        return instance
    end
    return cls
end

local Human = class()
function Human:life()
    print("almost 100 years.")
end
local Programmer = class()
function Programmer:coding()
    print("sub 1 year.")
end
local My = class(Human, Programmer)
local yuzixin = My.new()
yuzixin:life()
yuzixin:coding()

成功打印出结果
almost 100 years.
sub 1 year.
为什么能继承成功?原因如下:

在yuzixin里找不到life和coding字段,去找元表cls,调用元方法__index
__index调用函数search,把所有的父类都找一遍
成功找到

多继承就这样成功啦!撒花!
注意写一次代码减少一年的生命哦……(悲伤doge脸

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容

  • 前言 元表对应的英文是metatable,元方法是metamethod。我们都知道,在C++中,两个类是无法直接相...
    胤醚貔貅阅读 986评论 0 2
  • 第一篇 语言 第0章 序言 Lua仅让你用少量的代码解决关键问题。 Lua所提供的机制是C不擅长的:高级语言,动态...
    testfor阅读 2,647评论 1 7
  • 前言 新的项目终于准备要真正开始使用Lua进行开发了,所以笔者最近也开始了对Lua的学习,从以前的强类型的静态语言...
    巨龙饿了阅读 1,517评论 0 3
  • 前言 元表对应的英文是metatable,元方法是metamethod。我们都知道,在C++中,两个类是无法直接相...
    BobWong阅读 1,034评论 0 9
  • Lua中每个值都有一个元表metatable,这个元表metatable是一个原始的Lua表table,元表met...
    JunChow520阅读 1,511评论 1 0