加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

lua继承

发布时间:2020-12-14 22:11:59 所属栏目:大数据 来源:网络整理
导读:第一部分:LUA的继承 充电站:元表 lua中的元表和js的原型非常相似,熟悉js的朋友应该发现了 在lua中,每一个表都有TA的元表metatable,lua默认创建一个不带元表的新表: t = {} print ( getmetatable t )) -- nil 设置元表 mt { name = "quick" } setmetata

第一部分:LUA的继承

充电站:元表

  • lua中的元表和js的原型非常相似,熟悉js的朋友应该发现了
  • 在lua中,每一个表都有TA的元表metatable,lua默认创建一个不带元表的新表:
t = {}
print(getmetatablet)) --nil
  • 设置元表
mt {name = "quick"}
setmetatable, mt)
assertgetmetatalbe) == )

LuaInherit lua继承

LuaInherit lua继承

图示代码:

--====================Person======================
local Person {}
Person.attack = 5

function :new(o)
    o = o or {}
    setmetatableself__index self
    return o
end

:setAttackattackattack
getAttack()
    end


HeroHero ()
Heroname = ""
skill ""


hero1hero2hero1 "金刚狼"
"甩开爪子切牛排"

hero2 ({"超人"})
hero2"内裤外穿走T台"


----====================================================
printKeysnametprint("======================" .. )
    for kv in pairs) do
        end
end


"Person")
"Person.__index"__index)

"Hero""Hero.__index""getmetatable(Hero).__index"getmetatable)."hero1""hero2" 结合log我们分析下:

======================Person
setAttack
__index
getAttack
new
attack
Person.Hero
skill
name
__index
Hero).hero1
skill
hero2
skill
[Finished in 0.0s]

转回正题

假如当我们调用hero1:setAttack(500)的时候,在hero1中是找不到setAttack方法的,这时候:

  1. lua会通过getmetatable(hero1)得到hero1的元表并到元表的__index域中去查找,箭头走向:**3---》2**
  2. 但仍然没找到,得到Hero元表并继续在其__index域中寻找,箭头走向:**1---》0**,这时候寻找到setAttack方法并且调用,由于setAttack方法,hero1会增加字段attack

第二部分:QUICK的继承

quick的继承实现要考虑到对C++对象的继承和对lua对象的继承。对lua对象的继承我们第一部分已经用元表机制说明。当我们在quick中用class新建类时,始终要清醒的明白,我们新建的类其实就是返回一个lua表(cls).

继承的核心代码见framework/functions.luaclass(classname,super)函数。

为了方便理解,上个图先:

quick-x class

quick-x class

函数class(classname,super)有两个参数:

  • 参数1:classname,见名知意,类名
  • 参数2:super
    • 1.super的类型:superType = type(super)
    • 2.superType可以为function,?table,当不为这两种类型的时候我们将之置为nil
    • 3.superType为function的时候,表示从C++对象继承,走图示2
    • 4.superType为table的时候,还要看其__ctype值,1表示继承自C++对象,走图1;2表示继承自lua表对象,走图3
    • 5.superType为nil的时候,从lua表继承,走图4

samples/coinFlip项目是个绝佳的例子,我们可以结合该范例进行理解。这里我就不赘述了。


更新:在谷歌邮件组Jacky的回复中,提到了另外一个朋友写的文章,非常不错,针对本文的第二部分讲解的很透彻,地址


你我是朋友,各拿一个苹果彼此交换,交换后仍然是各有一个苹果;倘若你有一个思想,我也有一种思想,而朋友间交流思想,那我们每个人就有两种思想了。 ——爱尔兰剧作家 萧伯纳





在quick-cocos2dx里, 通过class() 函数进行类的定义

下面贴出quick-cocos2d-x-2.2.1-rc 里 class()的源码

?
function class(classname,super)
    local superType = type(superlocal cls
?
    if superType ~= "function" and superType ~"table" then
        superType nil
        super nil
    end
?
    if superType == or (super and super.__ctype == 1) then
        -- inherited from native C++ Object
        cls = {}
?
        then
            -- copy fields from super
            for k,v in pairsdo 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
?
        function cls.new(...)
            local instance = cls.__create)
            -- copy fields from class to native object
            (clsdo instanceend
            instance.class = cls
            instance:ctorreturn instance
        else
        -- inherited from Lua Object
        if super then
            cls }
            setmetatable(cls,{__index = super})
            cls.super else
            cls {ctor end}
        2 -- lua
        cls.__index = cls
?
        },cls)
            instance.class end
    return cls
end

我们先考虑最简单的情况, 在没有继承的情况下定义一个类ClassA

--ClassA.lua local ClassA = class("ClassA") ClassA.field1 "this is field1" return ClassA
--main.lua require) local InstanceA = ClassA.new)

这种情况下, ClassA 跟InstanceA的关系如下图

InstanceA的metatable为ClassA,而且ClassA.__index = ClassA,因此,对于InstanceA找不到的属性, 将在ClassA里进行查找。 需要注意的是,ClassA里的属性比如field1,是相当于类变量的概念,所有实例都公用该属性,并非各自维护该字段的拷贝。

下面如果要再定义ClassB,从ClassA 进行继承

--ClassB.lua local ClassB "ClassB",)) ? return ClassB

这种情况下, ClassB 跟InstanceB,ClassA的关系如下图

同理,InstanceB里没有定义的属性, 将首先在ClassB里进行搜索, 如果ClassB里搜不到, 将向上追寻到ClassA里。

上面考虑的都只是针对纯Lua类, 在实际情况中, 我们需要对C++里生成的对象(userdata)进行扩展, 可以如下定义

--ClassC.lua local ClassC "ClassC",102)">) --调用C++接口创建一个原生对象(userdata),并且给该对象绑定一个peer(table),这里我们以创建一个CCNode为例 local node = CCNode:create) --原生对象(userdata) local peer } tolua.setpeer(node,peer ) return node return ClassC

ClassC跟InstanceC的关系如下图

在调用InstanceC(实际上是一个userdata)上的某个方法时, 首先会先去这个userdata绑定的peer这个table里寻找这个方法,如果找不到才会去c++那层调用。

所以我们可以通过给peer添加几个方法从而实现给InstanceC(userdata)扩展方法, 实际情况上也确实如此,在quick里,有几个专门的类,CCNodeExtend,CCLayerExtend,CCSceneExtend,CCSpriteExtend, 使用比如 CCNodeExtend.extend(someCCNodeInstance),可以生成一个特殊的peer, 这个peer的metatable为CCNodeExtend, 这样我们就可以在someCCNodeInstance上调用CCNodeExtend定义了而原本CCNode没有的方法, 从而实现扩展。

下面再考虑ClassD从ClassC继承的情况

--ClassD.lua local ClassD "ClassD",0)">"ClassC") ? ? return ClassD

关系图:

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读