【cocos2d-x3.2游戏开发】 lua 类, 继承, 面向对象
本文转载自http://blog.csdn.net/teng_ontheway/article/details/38900211 1.lua中的类 lua中其实是没有类的,有的只是表(table),而类之间的继承也就是将父类的表连到了一起,派生类中没有找到的属性和方法就通过元表查找父类 2.lua中类的属性 classA = {width =10,height=10} classA={} classA.width=10 classA.height=10 两种方法都可以,通过点self.width统一调用 3.类方法 [cpp]view plaincopy
函数的声明和调用可以用":"和".",属性调用全部用点"." 4.类与元表的用法 lua查找一个表元素时的规则,其实就是如下3个步骤: 例如:
father={ house=1 } son={ car=1 } setmetatable(son,father)--把son的metatable设置为father print(son.house) 输出结果是nil,如果代码改为
father={ house=1 } father.__index=father--把father的__index方法指向自己 son={ car=1 } setmetatable(son,father) print(son.house) 输出的结果就为1了
localBox=class("Box",function(filename) returncc.Sprite:create(filename) end) Box.__index=Box 设置Box的元表的__index方法为自己,当派生类"SmallBox"派生自"Box",如果在SmallBox中查找不到的属性和方法,就检索元表,当然不是直接从元表中直接检索,是检索元表下的__index,如果__index为nil,则返回nil,如果__index是一个表,那么就到__index方法所指的表中查找对应的属性和方法 具体可以参考:Lua查找表元素过程(元表、__index方法是如何工作的) 5.Cocos2dx中的类 lua没有面向对象一说,cocos为我们准备了class的lua端函数,我们参考quick的class函数,里面还有对应的例子
--[[-- 创建一个类 ~~~lua --定义名为Shape的基础类 localShape=class("Shape") --ctor()是类的构造函数,在调用Shape.new()创建Shape对象实例时会自动执行 functionShape:ctor(shapeName) self.shapeName=shapeName printf("Shape:ctor(%s)",self.shapeName) end --为Shape定义个名为draw()的方法 functionShape:draw() printf("draw%s",self.shapeName) end -- --Circle是Shape的继承类 localCircle=class("Circle",Shape) functionCircle:ctor() --如果继承类覆盖了ctor()构造函数,那么必须手动调用父类构造函数 --类名.super可以访问指定类的父类 Circle.super.ctor(self,"circle") self.radius=100 end functionCircle:setRadius(radius) self.radius=radius end --覆盖父类的同名方法 functionCircle:draw() printf("draw%s,raidus=%0.2f",self.shapeName,self.raidus) end -- localRectangle=class("Rectangle",Shape) functionRectangle:ctor() Rectangle.super.ctor(self,"rectangle") end -- localcircle=Circle.new()--输出:Shape:ctor(circle) circle:setRaidus(200) circle:draw()--输出:drawcircle,radius=200.00 localrectangle=Rectangle.new()--输出:Shape:ctor(rectangle) rectangle:draw()--输出:drawrectangle ~~~ ###高级用法 class()除了定义纯Lua类之外,还可以从C++对象继承类。 比如需要创建一个工具栏,并在添加按钮时自动排列已有的按钮,那么我们可以使用如下的代码: ~~~lua --从cc.Node对象派生Toolbar类,该类具有cc.Node的所有属性和行为 localToolbar=class("Toolbar",function() returndisplay.newNode()--返回一个cc.Node对象 end) --构造函数 functionToolbar:ctor() self.buttons={}--用一个table来记录所有的按钮 end --添加一个按钮,并且自动设置按钮位置 functionToolbar:addButton(button) --将按钮对象加入table self.buttons[#self.buttons+1]=button --添加按钮对象到cc.Node中,以便显示该按钮 --因为Toolbar是从cc.Node继承的,所以可以使用addChild()方法 self:addChild(button) --按照按钮数量,调整所有按钮的位置 localx=0 for_,buttoninipairs(self.buttons)do button:setPosition(x,0) --依次排列按钮,每个按钮之间间隔10点 x=x+button:getContentSize().width+10 end end ~~~ class()的这种用法让我们可以在C++对象基础上任意扩展行为。 既然是继承,自然就可以覆盖C++对象的方法: ~~~lua functionToolbar:setPosition(x,y) --由于在Toolbar继承类中覆盖了cc.Node对象的setPosition()方法 --所以我们要用以下形式才能调用到cc.Node原本的setPosition()方法 getmetatable(self).setPosition(self,x,y) printf("x=%0.2f,y=%0.2f",y) end ~~~ **注意:**Lua继承类覆盖的方法并不能从C++调用到。也就是说通过C++代码调用这个cc.Node对象的setPosition()方法时,并不会执行我们在Lua中定义的Toolbar:setPosition()方法。 @paramstringclassname类名 @param[mixedsuper]父类或者创建对象实例的函数 @returntable ]] functionclass(classname,super) localsuperType=type(super) localcls ifsuperType~="function"andsuperType~="table"then superType=nil super=nil end ifsuperType=="function"or(superandsuper.__ctype==1)then --inheritedfromnativeC++Object cls={} ifsuperType=="table"then --copyfieldsfromsuper fork,vinpairs(super)docls[k]=vend cls.__create=super.__create cls.super=super else cls.__create=super cls.ctor=function()end end cls.__cname=classname cls.__ctype=1 functioncls.new(...) localinstance=cls.__create(...) --copyfieldsfromclasstonativeobject doinstance[k]=vend instance.class=cls instance:ctor(...) returninstance end else --inheritedfromLuaObject ifsuperthen cls={} setmetatable(cls,{__index=super}) cls.super=super else cls={ctor=function()end} end cls.__cname=classname cls.__ctype=2--lua cls.__index=cls functioncls.new(...) localinstance=setmetatable({},cls) instance.returninstance end end returncls end
6. 调用一个实例: 假设派生自一个cocos的类 Sprite
--class可以传1、2个参数 --@param类名,内部做记录而已,一般和返回的类名一致即可 --@param如果传参数2使用当前函数作为构造函数如果没参数2默认的构造函数 localBox=returncc.Sprite:create(filename) end) --设置元彪更改元表默认的元方法 --访问table中不存在的字段时,解释器查找__index的元方法,否则返回nil --多用于继承http://blog.csdn.net/q277055799/article/details/8463883 Box.__index=Box Box.isDead=false--定义属性 --构造函数(会自动调用) --外界构造时可以传任意参数XXX.new(...) functionBox:ctor(pic_path) localfunctiononNodeEvent(event) if"enter"==eventthen Box:onEnter(pic_path) elseif"exit"==eventthen Box:onExit() end end self:registerScriptHandler(onNodeEvent) localfunctiononUpdate() end self:scheduleUpdateWithPriorityLua(onUpdate,0) end functionBox:onEnter(pic_path) end functionBox:onExit() end functionBox.create(parent,position) localbox=Box.New("data/box.png") parent:addChild(box) returnbox end returnBox
localBomb=class("Bomb") 7.我们常见cocos2dx的例子中有大量的extend和tolua.getpeer用法如下:
localTimelineTestScene=class("TimelineTestScene") TimelineTestScene.__index=TimelineTestScene functionTimelineTestScene.extend(target) localt=tolua.getpeer(target) ifnottthen t={} tolua.setpeer(target,t) end setmetatable(t,TimelineTestScene) returntarget end functionTimelineTestScene.create() localscene=TimelineTestScene.extend(cc.Scene:create()) returnscene end 用的时tolua.getpeer,其实它的功能就相当于调用了class,所以请远离extend吧 class("TimelineTestScene",cc.Scene) TimelineTestScene.__index=TimelineTestScene (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |