Skip to content

lua面向对象

我们知道lua是非面向对象的语言,但lua的table异常强大,利用table实现面向对象并非难事

在实现面向对象前,我们需要理解table的一个元方法__index,网上看到一段流程图,讲解的比较清晰,就套用了 假设我们要在表p中查找talk这个键所对应的值,请看下面的流程图:

mermaid
> p中有没有talk这个键? `有 –> 返回talk对应的值`
        |
       没有
        |
p中是否设置过metatable? `否 –>  返回nil`
        |

        |
在p的metatable中有没有__index这个键? `没有 –>  返回nil`
        |

        |      
在p的metatable中的__index这个键对应的表中有没有talk这个键? `没有 –> 返回nil`
        |
        `有,返回getmetatable(p).__index.talk`

按照我们常用习惯,new一个对象出来,那么实现思路如下(写一个全局函数class):

lua
function class()
    local _class = {}
    _class.new = function(...)
        local obj = {}
        return obj
    end
    return _class
end

按照我的个人习惯,会把下面一段代码单独保存为一个lua文件,暂定为test.lua

lua
local cc = class()

function cc:excute(d)
    print('excute:' .. d)
end

return cc

local class_test = require 'test' 得到一个class对象 (实际为我们class函数中的_class表)
local d = class_test.new() 得到一份class_test的实例化对象 (实际为class函数中的obj表)

d:excute('this is a test')
我们期望的结果是打印 this is a test,然后结果并非如此,会提示找不到 excute方法
其实想想很简单,执行的d中的excute方法,而d实际上是个空表, excute方法是属于class_test类的,所以我们只要改变__index元表指向即可

lua
function class()
    local _class = {}
    _class.new = function(...)
        local obj = {}

        --改变元表指向
        setmetatable(obj,{__index=_class})
        return obj
    end
    return _class
end

几行代码就可以实现面向对象的功能,当然这只是很基础的功能,后面再说说加入继承和构造函数