cocos2dx-lua 对lua项目中class(sub,super)的理解

lua 模拟面向对象的继承通常是通过class方法,今天简析一下对class的理解,先例子
local MyApp = class("MyApp", cc.load("mvc").AppBase)

这是MyApp里的一个方法继承语句,class方法内部两个参数,一个是新建类简称A ,另一个是A继承的父类的类简称B,这句代码可以使得生成的A类继承B类后返回名为MyApp的新的子类。
重点内容
问题,class方法是如何实现模拟lua继承的呢?
class有三种继承情况,
1、第一种是继承一个方法,

local LogoScene = class("LogoScene", function()
    return cc.Scene:create()
end)

2、第二种继承一个C语言原生类

local LogoScene = class("LogoScene", cc.Scene)

3、继承一个lua类

local LogoScene = class("LogoScene", {})

下面看一下面class的代码

function class(classname, ...)
    local cls = {__cname = classname}
    --这里可以看出lua的cocos模拟的class方法支持多继承
    local supers = {...}
    for _, super in ipairs(supers) do
        local superType = type(super)
        assert(superType == "nil" or superType == "table" or superType == "function",
            string.format("class() - create class \"%s\" with invalid super class type \"%s\"",
                classname, superType))
        --这里是class继承的第一种情况,继承一个方法(在子类new之前先执行的内建函数__create)
        if superType == "function" then
            assert(cls.__create == nil,
                string.format("class() - create class \"%s\" with more than one creating function",
                    classname));
            -- if super is function, set it to __create
            --如果super是一个方法,把super直接复制给内建函数__create
            cls.__create = super
        --下面是class的第二,第三种情况,当传过来的值是table类型的时候
        --这里需要明确的一点是,在lua里table其实还分两种,一种是lua的table,另一种是c里转换过来的一种类型叫userTable,在用tolua++绑定cocos2dx引擎的时候,tolua++会为userTable类型的类在执行create方法的时候为其加入.isclass属性(大家可以用执行dump(cc.Layer)观察)
        elseif superType == "table" then
            --下面这种是第二种情况
            --如果有.isclass这个值则说明是从c++转换过来的数据结构
            if super[".isclass"] then
                -- super is native class
                assert(cls.__create == nil,
                    string.format("class() - create class \"%s\" with more than one creating function or native class",
                        classname));
                --这里可以看出这种继承了c结构的子类其实也只是执行子类之前执行了一个创建父类对象的方法
                cls.__create = function() return super:create() end
            else
                --后面这个是第三种情况,子类是lua继承的父类也是lua,这里有另一个内建函数__supers,他的作用是存放父类数组(父类可能不止一个)
                -- super is pure lua class
                cls.__supers = cls.__supers or {}
                cls.__supers[#cls.__supers + 1] = super
                if not cls.super then
            -- set first super pure lua class as class.super
                    cls.super = super
                end
            end
        else
            error(string.format("class() - create class \"%s\" with invalid super type",
                        classname), 0)
        end
    end
    --__index方法是一个“操作指南”
    --下面的__index对于继承功能的模拟也很关键
    --更简单的说就是在我调用方法的时候,class是如何实现继承功能的(当子类搜索自己的函数未果,就会按照__index的指引去搜索父类,去寻找方法)
    cls.__index = cls
    --如果子类的父类不存在或者只存在只有一个,那么把索引方法指向唯一的父类
    if not cls.__supers or #cls.__supers == 1 then
        setmetatable(cls, {__index = cls.super})
    else
     --如果子类的存在多个父类,那么把索引方法会遍历所有的父类
        setmetatable(cls, {__index = function(_, key)
            local supers = cls.__supers
            for i = 1, #supers do
                local super = supers[i]
                if super[key] then return super[key] end
            end
        end})
    end

    if not cls.ctor then
        -- add default constructor
        cls.ctor = function() end
    end
    --这里的new方法是模拟cocos2dx里面的创建对象,下面的代码一目了然
    cls.new = function(...)
        local instance
        if cls.__create then
            --这里需要注意的一件事是,
            --
            --local LogoScene = class("LogoScene", function(argu)
            --    --dump(argu)
            --    return cc.Scene:create()
            --end)
            --function LogoScene:ctor(argu)
            --  --dump(argu)
            --end
            --上面的和这个栗子如果调用  LoginScene:create(argu)方法会将argu里的参数传到class后面的function里面,执行完function之后再执行ctor。
            instance = cls.__create(...)
        else
            instance = {}
        end
        setmetatableindex(instance, cls)
        instance.class = cls
        instance:ctor(...)
        return instance
    end
    --这里只是为了模拟cocos2dx的编程习惯
    cls.create = function(_, ...)
        return cls.new(...)
    end

    return cls
end

到这里class的基本用法就写完了,usertable找个数据结构涉及到lua虚拟机内部的结构,后面研究透彻之后会继续补充。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值