您的位置:首页 > 移动开发 > Cocos引擎

quick-cocos2dx lua里对class的定义

2014-12-12 13:56 357 查看
转载:http://www.swfdiy.com/?p=1663

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

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

function class(classname, super)
local superType = type(super)
local cls

if superType ~= "function" and superType ~= "table" then
superType = nil
super = nil
end

if superType == "function" or (super and super.__ctype == 1) then
-- inherited from native C++ Object
cls = {}

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

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
-- 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

return cls
end


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

--ClassA.lua
local ClassA = class("ClassA")
ClassA.field1 = "this is field1"
return ClassA


--main.lua
local ClassA = require("ClassA")
local InstanceA = ClassA.new()


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



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

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

--ClassB.lua
local ClassB = class("ClassB", require("ClassA"))

return ClassB


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



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

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

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

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 = class("ClassD", require("ClassC"))

return ClassD


关系图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐