0基础lua学习(十六)lua的多态 base

多态base

使用lua实现C++类似的多态,看起来略微难了一些,这个demo,默认提供了 init类似构造函数的时机。

--base.lua代码
--保存类类型的虚表
local _class = {}
function BaseClass(super)
    -- 生成一个类类型
    local class_type = {}
    -- 在创建对象的时候自动调用
    class_type.__init = false
    class_type.__delete = false
    class_type.super = super
    class_type.New = function(...)

        -- 生成一个类对象
        local obj = {}
        obj._class_type = class_type

        -- 在初始化之前注册基类方法
        setmetatable(obj, { __index = _class[class_type] })

        -- 调用初始化方法
        do
            local create
            create = function(c, ...)
                if c.super then
                    create(c.super, ...)
                end
                if c.__init then
                    c.__init(obj, ...)
                end
            end

            create(class_type, ...)
        end

        -- 注册一个delete方法
        obj.DeleteMe = function(self)
            local now_super = self._class_type
            while now_super ~= nil do
                if now_super.__delete then
                    now_super.__delete(self)
                end
                now_super = now_super.super
            end
        end

        return obj
    end

    local vtbl = {}
    _class[class_type] = vtbl

    setmetatable(class_type, {__newindex =
    --table key value
        function(t,k,v)
            vtbl[k] = v
        end
        ,
        __index = vtbl, --For call parent method
    })

    if super then
        setmetatable(vtbl, {__index =
            function(t,k)
                local ret = _class[super][k]

                return ret
            end
        })
    end

    return class_type
end
--main.lua代码
require"base"

father = father or BaseClass()
function father:__init()
    print("father:init")
end

function father:Bind()
    print("father:Bind")
end

function father:play()
    print("father:play")
end


son = son or BaseClass(father)

function son:__init()
    print("son:init")
end

function son:Bind()
    print("son:Bind")
end

function son:UnBind()

end


a = nil
a = son:New()
a:play()
a:Bind()

console:
father:init
son:init
father:play
son:Bind

多态base解析

1.首先要明确
father = father or BaseClass( )和 son = son or BaseClass(father)
有一个共同的表local _class = {},也就是虚表。

2.father = father or BaseClass(),我们会保存__class[class_type] = vtbl
classtype是key,value是表
返回的表是 class_type

                vtbl
                 {__newindex =
                    function(t,k,v)   
                        vtbl[k] = v
                    end,
                  __index = vtbl
                 }

3.function father:__init(),会将class_type表中的__init 从布尔,变为函数
4.function father:Bind(),没有Bind函数,所以会调用vtbl表中的__newindex,因为我们没有Bind的key

    function(t,k,v)   
        vtbl[k] = v
    end

这样vtbl中添加了一个Bind的key,value是函数
5.son = son or BaseClass(father)同理,但是它的vtbl会添加__index = function(t,k)的函数

6.function son:__init(),会将class_type表中的__init 从布尔,变为函数
7.function son:Bind(),所以会调用

    function(t,k,v)   
        vtbl[k] = v
    end

向son的vtbl表中加入函数
8.a = son:New()这是
son = son or BaseClass(father)里面的new方法,调用父类的init,然后调用子类的init,然后返回
_class[class_type],这个是son的vtbl表。(_class里面有两个vtbl,key分别是father的class_type和son的class_type,其值是各自的vtbl表)

9.a:play()这是调用父类的play方法,首先去son的vtbl表中查找,通过__index调用了

function(t,k)
 local ret = _class[super][k]
 return ret
end

_class[super]这是访问虚表中的,father的vtbl,然后我们找到了,然后进行调用。
注意:如果我们换成a:play1(),就会报错all method ‘play1’ (a nil value) ,也就是你声明函数,要加到父类的表里
也就是下面这步

function father:play()
    print("father:play")
end

10.a:Bind(),其实就是找son的vtbl,直接找到了函数,然后调用。

小结:

  • 我们声明的 son继承 father之前,需要创建两个表,每个表里都有一个vtbl , 有一个总表_class来管理
  • __newindex 实现的是,我们创建函数添加函数,加到vtbl 表里
  • __index 实现的是,继承的实现。即访问父类里面的函数,如果子类实现了,就访问子类的。
  • t 是table、k是key、v是value

看着是有点乱,但是你多看几遍,你就会有所收获。
这个代码可以说,我们在开发游戏的时候,使用的base代码。

转载于:https://www.cnblogs.com/hiwoshixiaoyu/p/10034975.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值