cocos2d-lua class 方法解释
lua中没有类的概念,有的只是表(table),而类之间的继承也就是将父类的表连到了一起,派生类中没有找到的属性和方法就通过元表查找父类,在cocos2d-lua中,封装好的class方法,完美的实现了类的继承,包括单继承,和多继承,class的源码如下(省去了一些不必要的代码):
_setmetatableindex = function(t, index)
if type(t) == "userdata" then
local peer = tolua.getpeer(t)
if not peer then
peer = {}
tolua.setpeer(t, peer)
end
_setmetatableindex(peer, index)
else
local mt = getmetatable(t)
if not mt then mt = {} end
if not mt.__index then
mt.__index = index
setmetatable(t, mt)
elseif mt.__index ~= index then
_setmetatableindex(mt, index)
end
end
end function class(classname, ...) --参数一:所要创建的类名,参数二:可选参数,可以使function,也可以是table,userdata等
local cls = {__cname = classname} local supers = {...}
for _, super in ipairs(supers) do --遍历可选参数
local superType = type(super)
if superType == "function" then
--如果是个function,那么就让cls的create方法指向他
cls.__create = super
elseif superType == "table" then --如果是个table
if super[".isclass"] then--如果是个原生cocos类,比如cc.Sprite,不是自定义的
cls.__create = function() return super:create() end
else
-- 如果是个纯lua类,自己定义的那种,比如a={}
cls.__supers = cls.__supers or {}
cls.__supers[#cls.__supers + ] = super--不断加到__supers的数组中
if not cls.super then
-- 把第一个遍历到的table作为cls的超类
cls.super = super
end
end end
end cls.__index = cls--不知道作用
if not cls.__supers or #cls.__supers == then --这个就是单继承,设置cls的元表的index为他的第一个超类
setmetatable(cls, {__index = cls.super})
else
setmetatable(cls, {__index = function(_, key)--羡慕是多继承,index指向一个函数,到时候找元素的时候会遍历函数
local supers = cls.__supers
for i = , #supers do
local super = supers[i]
if super[key] then return super[key] end
end
end})
end if not cls.ctor then
-- 增加一个默认构造函数
cls.ctor = function() end
end
cls.new = function(...) --新建方法,这个也是比较重要的方法
local instance
if cls.__create then
--如果有create方法,那么就调用,正常情况下,自定义的cls是没有create方法的。
--会不断的向上寻找元类的index,直到找到原生cocos类,比如sprite,然后调用sprite:create()
--返回一个原生对象,通过调试代码,可以得出这些 instance = cls.__create(...)
else
instance = {}--没有,说明根目录不是cocos类,而是普通类
end
--这个方法也比较关键,设置instance的元类index,谁调用new了,就把他设置为instance的元类index
--具体可以看代码
_setmetatableindex(instance, cls)
instance.class = cls
instance:ctor(...)--调用构造函数
return instance
end
cls.create = function(_, ...)
return cls.new(...)
end return cls
end
通过以上方法,可以实现类的继承,那么如何调用这个方法呢,看下面的事例
为了说明事例,我又精简了上面的代码,便于我们说明
local _setmetatableindex
_setmetatableindex = function(t, index) -- print("总是Sprite=" .. t.type )
local mt = getmetatable(t)
if not mt then
mt = {}
print("第一个分支")
end
if not mt.__index then
mt.__index = index
setmetatable(t, mt)
print("第二个分支")
elseif mt.__index ~= index then
print("第三个分支")
_setmetatableindex(mt, index)
end end function class2(classname, ...)
local cls = {__cname = classname} local supers = {...}
for _, super in ipairs(supers) do
local superType = type(super) if superType == "function" then
cls.__create = super elseif superType == "table" then
if super[".isclass"] then
cls.__create = function() return super:create() end
print("走上面")
else
print("走下面") cls.__supers = cls.__supers or {}
cls.__supers[#cls.__supers + ] = super
if not cls.super then
cls.super = super
end
end end
end cls.__index = cls
if not cls.__supers or #cls.__supers == then
setmetatable(cls, {__index = cls.super}) end cls.new = function(...)
print("走一遍")
local instance
if cls.__create then
instance = cls.__create(...)
print("有函数")
else
instance = {}
print("无函数")
end _setmetatableindex(instance, cls) instance.class = cls return instance
end
cls.create = function(_, ...)
return cls.new(...)
end
return cls
end
调用:
--第一个类,这里模仿cocos的Sptite类
local Sprite={}
Sprite.type="Sprite"
Sprite.wenqian1=
Sprite[".isclass"]=true
function Sprite:create(o)
o=o or {}
setmetatable(o,self) ;
self.__index=self; return o
end
--第二个类,这里他继承了Sprite类
GameSprite = class2("GameSprite",
-- function() return Sprite:create() end
Sprite
)
GameSprite.wenqian2= --第三个类,这里继承了 GameSprite类
testClass=class2("testClass",
-- function()
-- return GameSprite:create()
-- end GameSprite--,GameSprite2
)
testClass.wenqian3=
--实例化一个testClass类的对象
local test=testClass:new()
print(test.wenqian1);
print(test.wenqian2)
print(test.wenqian3)
运行结果如下:
[LUA-print] 走上面
[LUA-print] 走下面
[LUA-print] 走一遍
[LUA-print] 有函数
[LUA-print] 第三个分支
[LUA-print] 第一个分支
[LUA-print] 第二个分支
[LUA-print] 111
[LUA-print] 222
[LUA-print] 333
通过class里面的代码,可以看出 返回的local test 实际上就是最顶层的Sprite 类的一个新建对象,然后他的元类的index为testClass,
而testClass的元类的index为GameSprite,从而wenqian1,wenqian2,wenqian3都能够正确的找到。
下面说一下错误的情况,之前由于学习lua比较仓促,没有细看class的原理,所以用了下面的错误方法调用local Sprite={}
Sprite.type="Sprite"
Sprite.wenqian1=
Sprite[".isclass"]=true
function Sprite:create(o)
o=o or {}
setmetatable(o,self) ;
self.__index=self; return o
end GameSprite = class2("GameSprite",
-- function() return Sprite:create() end
Sprite
) GameSprite.wenqian2= testClass=class2("testClass",
function()
return GameSprite:create()
end
) testClass.wenqian3=
local test=testClass:new()
--print( getmetatable(test).__index==GameSprite)
--print( getmetatable(getmetatable(test)).__index==testClass)
print(test.wenqian1);
print(test.wenqian2)
print(test.wenqian3)
改动的地方就是红色字体部分,以前第二个参数是GameSprite类,现在成了一个返回GameSprite:create方法,运行结果如下:
[LUA-print] 走上面
[LUA-print] 走一遍
[LUA-print] 走一遍
[LUA-print] 有函数
[LUA-print] 第三个分支
[LUA-print] 第一个分支
[LUA-print] 第二个分支
[LUA-print] 有函数
[LUA-print] 第三个分支
[LUA-print] 第三个分支
[LUA-print] 第一个分支
[LUA-print] 第二个分支
[LUA-print] 111
[LUA-print] 222
[LUA-print] nil
从结果可知,test 本身的属性wenqian3没有取出来,是空值,这是为什么呢,通过分析代码可以知道,new的方法走了两次,
使得Sprite的对象的元类的index成了GameSprite,而GameSprite的元表的元表成了testClass,而不是元表的index是testClass,也就是说
Sprite的对象无法找到wenqian3字段,那么他就会去他元表的index字段,
也就是GameSprite中去找,但是GameSprite依然无法提供wenqian3,所以GameSprite去他的元表的index中
找,但是通过上面的程序得知GameSprite的元表的index不是testClass,所以无法找到他
所以综上所述得知,如果新建的类继承的直接是cocos系列的类,那么可以用比如直接写类名,或者返回create函数
而如果是继承的自定义的类,那么最简单,最直接的还是直接写类名,而写函数的话,如果处理不当可能会出现奇怪的错误,当然函数也是可以实现的,具体情况需要具体分析
cocos2d-lua class 方法解释的更多相关文章
- Cocos2d Lua 越来越小样本 内存游戏
1.游戏简介 一个"记忆"类的比赛游戏.你和电脑对战,轮到谁的回合,谁翻两张牌,假设两张牌一样.就消掉这两张牌,得2分,能够继续翻牌,假设两张牌不一样,就换一个人.直到最后.看谁的 ...
- #Cocos2d+lua#android+Eclipse工程编译设置
用Elicpse编译cocos2d+lua的工程几点注意点记录: 1.设置工程属性Windows->Preferences->NDK目录 2.右键Android Tools->Add ...
- Info.plist和pch文件的作用,UIApplication,iOS程序的启动过程,AppDelegate 方法解释,UIWindow,生命周期方法
Info.plist常见的设置 建立一个工程后,会在Supporting files文件夹下看到一个“工程名-Info.plist”的文件,该文件对工程做一些运行期的配置,非常重要,不能删除 注:在旧 ...
- es6的map()方法解释
es6的map()方法解释 map方法的作用不难理解,即“映射”,也就是原数组被“映射”成对应新数组.下面这个例子是数值项求平方: var data = [1, 2, 3, 4]; var arr ...
- vue第六单元(vue的实例和组件-vue实例的相关属性和方法-解释vue的原理-创建vue的组件)
第六单元(vue的实例和组件-vue实例的相关属性和方法-解释vue的原理-创建vue的组件) #课程目标 掌握vue实例的相关属性和方法的含义和使用 了解vue的数据响应原理 熟悉创建组件,了解全局 ...
- [cocos2d] 调用动画方法
利用texture atlases生成动画 中讲到如何添加动画,如果想要调用已添加的动画怎么办? 在1.0.1版本以前的cocos2d添加动画的方法为: CCAnimation *anim = [CC ...
- cocos2dx3.0导出自定义类到lua的方法详细步骤
我写了一个用3.0的工具导出类到lua,自动生成代码的方法. 以前要导出c++类到lua,就得手动维护pkg文件,那简直就是噩梦,3.0以后就会感觉生活很轻松了. 下面我就在说下具体做法.1.安装必要 ...
- lua元方法
lua中有元表的概念,元表类似于基类的功能, 在元表中有两个方法可以很好的认识元表: __index和__newindex __index用于查询 对表中的字段进行访问时,如果该表有元表,并且 表中没 ...
- 重载Cocos2D生存期的方法
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交 ...
随机推荐
- 每日学习心得:CustomValidator验证控件验证用户输入的字符长度、Linq 多字段分组统计、ASP.NET后台弹出confirm对话框,然后点击确定,执行一段代码
2013-9-15 1. CustomValidator验证控件验证用户输入的字符长度 在实际的开发中通常会遇到验证用户输入的字符长度的问题,通常的情况下,可以写一个js的脚本或者函数,在ASP ...
- [原]Fedora Linux环境下的应用工具总结
一.办公类软件 1.Office办公:WPS 二.网络通信类软件 1.浏览器:Chrome 2.远程桌面:rdesktop(适用于Windows系列) 三.操作系统设置与优化 1.3D桌面管理:Com ...
- [转]LOG4J汇编教程edit Z10
摘自:http://wucuixia.blog.sohu.com/12057602.html LOG背景 我们在编程时经常不可避免地要使用到一些日志操作,比如开发阶段的调试信息.运行时的日志记录及审计 ...
- get utc+8 当时时间
/// <summary> /// get utc+8 当时时间 /// </summary> /// <returns></returns> publ ...
- android 反编译 逆向工具整理
需要准备的道具需要哪些软件会在后面逆向过程中详细介绍,这里先大致罗列一下 android一台root并安装了xposed框架的手机(主要是为了脱壳) 类似[海马玩]这种模拟器 android-kill ...
- Redis-sentinel监控
Sentinel介绍 Redis的 Sentinel 系统用于管理多个Redis服务器, 该系统执行以下三个任务: 监控(Monitoring) 提醒(Notification) 自动故障迁移(Aut ...
- Winform/WPF国际化处理
1.Winfrom国际化处理方式 ==> Winform中国际化支持可将UI页面和.cs文件分开处理 处理窗体方式如下:1.选择Form窗体设置其--Language(默认中文--Default ...
- 328. Odd Even Linked List
Given a singly linked list, group all odd nodes together followed by the even nodes. Please note her ...
- C#全角和半角转换
在计算机屏幕上,一个汉字要占两个英文字符的位置,人们把一个英文字符所占的位置称为"半角",相对地把一个汉字所占的位置称为"全角".在汉字输入时,系统提供&quo ...
- Maven实战
一.不要重复造轮子 极限编程(XP)是近些年在软件行业红的发紫的敏捷开发方法,强调拥抱变化. Maven帮助XP团队实现一些核心价值: 1.简单.Maven暴露了一组一致.简洁的操 ...