本文转载自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
3.类方法
[cpp]view plaincopy
函数的声明和调用可以用":"和".",属性调用全部用点"."
4.类与元表的用法
lua查找一个表元素时的规则,其实就是如下3个步骤:
4.1.在表中查找,如果找到,返回该元素,找不到则继续
4.2.判断该表是否有元表,如果没有元表,返回nil,有元表则继续
4.3.判断元表有没有__index方法,如果__index方法为nil,则返回nil;如果__index方法是一个表,则重复1、2、3;如果__index方法是一个函数,则返回该函数的返回值
例如:
father={
house=1
}
son={
car=1
}
print(son.house)
father={
house=1
}
father.__index=father--把father的__index方法指向自己
son={
car=1
}
setMetatable(son,father)
print(son.house)
输出的结果就为1了
这就解释了为什么我们经常在cocos2dx的类中经常见到如下
returncc.Sprite:create(filename)
end)
设置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")
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()
--类名.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
--因为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()方法
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类名
@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
传入是一个父类的话,会调用cls.new函数,然后创建实例,调用ctor构造函数
6. 调用一个实例:
假设派生自一个cocos的类 Sprite
--class可以传1、2个参数
--@param类名,内部做记录而已,一般和返回的类名一致即可
localBox=returncc.Sprite:create(filename)
end)
--设置元彪更改元表默认的元方法
--访问table中不存在的字段时,解释器查找__index的元方法,否则返回nil
--多用于继承http://blog.csdn.net/q277055799/article/details/8463883
--外界构造时可以传任意参数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)
parent:addChild(Box)
returnBox
end
returnBox
如果是一个table,可以直接使用
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