Lua面向对象

…衆ロ難τιáo~ 提交于 2020-01-25 03:13:16

一、认识lua中的面向对象编程

lua中的table就是一种对象,它和其它语言中的对象一样拥有一个独立于其值的标识(self);使用self参数是所有面向对象语言的一个核心,大多数面向对象语言都能对程序员隐藏部分self参数,从而使得程序员不必显式声明这个参数,Lua中使用冒号,则能隐藏self参数,冒号只是一种语法便利,并没有引入新的东西;

在一个函数中,我们往往不希望使用到全局变量而希望使用自定义局部变量以及传入的参数;观察注释部分,这里的Account使用的是外部变量,那么一旦在外部将Account置为nil,那么我们使用a.withdraw执行函数时就会出错;修改之后,我们使用self作为参数来传入函数内,Account:withdraw(v)等价于Account.withdraw(self.v)

function Account:withdraw(v)
        --Account.balance=Account.balance-v
        --print (Account.balance)
        self.balance=self.balance-v
        print(self.balance)
end

local a=Account
Account=nil
a:withdraw(10)

Lua冒号语法糖,隐藏了self参数,默认将自身作为函数的第一个参数传入;在调用时也可以显式传入该参数,并不一定要传入自身,这是就要用到点操作符; 

二、类的实现

类的实现原理是通过元方法__index来实现的(也是基于__index的原理);

我们可以用lua表来实现面向对象,最简单的是将__index指向基类,另一种方法是在实例化对象时直接将基类的成员深拷贝给子类;

基本思想

  • lua 中的 function 可以用来表示方法,那么Lua中的类可以通过 table + function 模拟出来。
  • 至于继承,可以通过 metetable 模拟出来(不推荐用,只模拟最基本的对象大部分时间够用了)。

Lua中类、继承和多继承的实现,基于原型的面向对象,没有类的概念,所有的对象都是实例;通过元表的__index元方法来实现类,继承就是在定义一个对象的时候,它已经继承了原型的所有行为,而且它还可以添加自己的行为,还可以重写原型的行为以实现多态;通过将self设置为元表,那么元表就可以视为一个对象的超类;

简易版本如下,通过new可以创建一个实例,它继承于base;

local base={}
function base.new()
    local t={}
    setmetatable(t,{__index=base})
    return t
end
return base

--测试
local test=base.new()

具体实现参考:云风-Lua中实现面向对象

这种实现方式完全达到了OO的目的,从创建一个类,到类的实例化,到类的继承,都完成了;

local _class={}

function class(super)
    local class_type={}
    class_type.ctor=nil
    class_type.super=super
    class_type.new=function(...)
        local obj={}
        do
            local create
            create=function(c,...)
                if c.super then
                    create(c.super,...)
                end
                if c.ctor then
                    c.ctor(obj,...)
                end
            end
            create(class_type,...)
        end
        setmetatable(obj,{__index=_class[class_type]})
        return obj
    end
    local vtbl={}
    _class[class_type]=vtbl
    setmetatable(class_type,{__newindex=function(t,k,v)
        vtbl[k]=v
    end})
    if super~=nil then
        setmetatable(vtbl,{__index=function(t,k)
            local v=_class[class_type][k]
            vtbl[k]=v
            return v
        end})
    end
    return class_type
end

--测试
local basetype=class()
function basetype:ctor()
    print("basetype:ctor")
end
function basetype:eat()
    print("basetype:eat")
end
local b=basetype.new()
b:eat()
local derivedtype=class(basetype)
function derivedtype:ctor()
    print("derivedype:ctor")
end
function derivedtype:eat()
    print("derivedtype:eat")    
end

local b=derivedtype.new()
local mt=getmetatable(b).__index
print(type(mt))
for k,v in pairs(mt) do
    print(k,v)
end

三、参考

OpenResty-面向对象

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!