Cocos2d+Lua 游戏开发中的奇技淫巧系列之三 Lua 多重继承的实现

先说一下上一篇文章提到的class()函数,它接受二个参数,第一个是类名,第二个是基类,也就是只它只能从一个继承一个基类。我们之前提到过,继承其实是要实现代码的复用,显然只有单个基类的继承是无法有效实现代码复用的。例个例子

 

Bird =class("Bird") --鸟

function Bird:Fly() --鸟会飞

    print("I can Fly")
  
end

Penguin =class("Penguin",Bird ) --企鹅,是一种鸟,所以它继承自鸟类,但是不会飞


function Penguin:Fly() --企鹅不会飞,所以要重写它的Fly函数

    print("I can'n Fly")
  
end


Fish = class("Fish")

function Fish:Swim() --鱼会游

    print("I can Swim")
  
end


Polarbear=class("Polarbear") --北极熊

function Polarbear:ILoveIce()--北极熊喜欢冰
   print("I Love ice")
end

上述的例子,企鹅是鸟的一种继承自鸟类,但是,企鹅已经不会飞了,所以它得重写Fly函数,让它不能飞。但是企鹅可以游泳,要实现企鹅游泳,我们可以给它写一个游泳的函数

function Penguin:Swim() --给企鹅加上会游泳的函数

    print("I can Swim")
  
end

同时,企鹅还喜欢冰,我们给它加上喜欢冰的函数

function Penguin:ILoveIce()--企鹅喜欢冰
   print("I Love ice")
end

这样,最终的代码应该是这样的

Bird =class("Bird") --鸟

function Bird:Fly() --鸟会飞

    print("I can Fly")
  
end



Fish = class("Fish")

function Fish:Swim() --鱼会游

    print("I can Swim")
  
end


Polarbear=class("Polarbear") --北极熊

function Polarbear:ILoveIce()--北极熊喜欢冰
   print("I Love ice")
end


Penguin =class("Penguin",Bird ) --企鹅,是一种鸟,所以它继承自鸟类,但是不会飞


function Penguin:Fly() --企鹅不会飞,所以要重写它的Fly函数

    print("I can'n Fly")
  
end


function Penguin:Swim() --给企鹅加上会游泳的函数
    print("I can Swim")
end

function Penguin:ILoveIce()--企鹅喜欢冰
   print("I Love ice")
end

额没有发觉,企鹅实现的Swim和ILoveIce函数,其实和鱼和北极熊的是一样的,我们已经给鱼写了一个了,为什么我们还要给企鹅要写一个一模一样的啊?我们是不是可以复用一下这个代码?现在只是几行代码,要是函数多了, 函数的代码多了,复制代码也很累的。比如,让企鹅继承自鸟类,然后再继承一下鱼类,熊类的接口,啊,企鹅就能像鱼一样游泳,像北极熊一样在冰上玩啦。

Penguin =class("Penguin",Bird,Fish,PolarBear) --企鹅,是一种鸟,同时拥有鱼,北极熊的能力,完美


function Penguin:Fly() --企鹅不会飞,所以要重写它的Fly函数

    print("I can'n Fly")
  
end

这样想想是不是很好啊,嗯,但是class的实现并不支持多重继承呀,好了,最重要的一步来了,我们就来改写class吧

function class(classname, super,...) --给class增加一个变参,支持多重继承
    local superType = type(super)
    local cls

    --如果父类既不是函数也不是table则说明父类为空
    if superType ~= "function" and superType ~= "table" then
        superType = nil
        super = nil
    end

    --如果父类的类型是函数或者是C对象
    if superType == "function" or (super and super.__ctype == 1) then
        -- inherited from native C++ Object
        cls = {}

        --如果父类是表则复制成员并且设置这个类的继承信息
        --如果是函数类型则设置构造方法并且设置ctor函数
        if superType == "table" then
            -- copy fields from super
            for k,v in pairs(super) do cls[k] = v end
            cls.__create = super.__create
            cls.super    = super
        else
            cls.__create = super
            cls.ctor = function() end
        end

        --设置类型的名称
        cls.__cname = classname
        cls.__ctype = 1

        --定义该类型的创建实例的函数为基类的构造函数后复制到子类实例
        --并且调用子数的ctor方法
        function cls.new(...)
            local instance = cls.__create(...)
            -- copy fields from class to native object
            for k,v in pairs(cls) do instance[k] = v end
            instance.class = cls
            instance:ctor(...)
            return instance
        end

    else
        --如果是继承自普通的lua表,则设置一下原型,并且构造实例后也会调用ctor方法
        -- inherited from Lua Object
        if super then
            cls = {}
            setmetatable(cls, {__index = super})
            cls.super = super
        else
            cls = {ctor = function() end}
        end

        cls.__cname = classname
        cls.__ctype = 2 -- lua
        cls.__index = cls

        function cls.new(...)
            local instance = setmetatable({}, cls)
            instance.class = cls
            instance:ctor(...)
            return instance
        end
    end
    
    local interfaces={...}
    for _,base in ipairs(interfaces) do
        for k,v in pairs(base) do --遍历所有的接口类
            if not cls[k] then
                cls[k] = clone(v) --假如这些成员都不存在,就深copy到子类
            end
        end
    end

    return cls
end

在这里,class 增加了三个参数:第一个参数是类名,第二个是主基类,第三个是变长参数,我们可以称之类接口类。首先,主类会继承父类的所有接口,将它们copy到父类,然后,再遍历接口类的所有成员,假如这些成员不存在,就copy到子类,这样就完美在实现了多重继承了。

这里,当父类和接口类同时存在成员,只保留父类的,接口类同时存在的成员,按定义顺序,先定义的,会被copy到子类,后定义的不会。这样个规则解决了重名函数和变更的问题。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值