cocos2dx +lua 面向对象

来自:http://blog.csdn.net/hapiman11/article/details/39271017

1.lua中的类

lua中其实是没有类的,有的只是表(table),而类之间的继承也就是将父类的表连到了一起,派生类中没有找到的属性和方法就通过元表查找父类

2.lua中类的属性

classA = {width =10, height=10}

classA={}

classA.width=10

classA.height=10

两种方法都可以,通过点self.width统一调用

3.类方法

 

1. function Box:collsion()
2.     -- 默认第一个参数隐藏传递self,可以通过self.xxx 调用属性和方法
3. end
4.   
5. function Box.create(self)
6.     --必须手动传递参数self,否则无法用self.xxx调用属性和方法
7. end
函数的声明和调用可以用":"和".",属性调用全部用点"."

 

4.类与元表的用法

lua查找一个表元素时的规则,其实就是如下3个步骤:

4.1.在表中查找,如果找到,返回该元素,找不到则继续

4.2.判断该表是否有元表,如果没有元表,返回nil,有元表则继续

4.3.判断元表有没有__index方法,如果__index方法为nil,则返回nil;如果__index方法是一个表,则重复1、2、3;如果__index方法是一个函数,则返回该函数的返回值

例如:

 

1. father = {
2.     house=1
3. }
4. son = {
5.     car=1
6. }
7. setmetatable(son, father) --把son的metatable设置为father
8. print(son.house)
输出结果是nil,如果代码改为

 

 

01. father = {
02.     house=1
03. }
04. father.__index = father -- 把father的__index方法指向自己
05. son = {
06.     car=1
07. }
08. setmetatable(son, father)
09. print(son.house)
输出的结果就为1了

这就解释了为什么我们经常在cocos2dx的类中经常见到如下

 

 

1. local Box = class("Box", function(filename)
2.         return cc.Sprite:create(filename)
3.     end)
4.   
5. Box.__index = Box
设置Box的元表的__index方法为自己,当派生类"SmallBox"派生自"Box",如果在SmallBox中查找不到的属性和方法,就检索元表,当然不是直接从元表中直接检索,是检索元表下的__index,如果__index为nil,则返回nil,如果__index是一个表,那么就到__index方法所指的表中查找对应的属性和方法

 

具体可以参考:Lua查找表元素过程(元表、__index方法是如何工作的)
 

5.Cocos2dx中的类

lua没有面向对象一说,cocos为我们准备了class的lua端函数,我们参考quick的class函数,里面还有对应的例子

 

001. --[[--
002.   
003. 创建一个类
004.   
005. ~~~ lua
006.   
007. -- 定义名为 Shape 的基础类
008. local Shape = class("Shape")
009.   
010. -- ctor() 是类的构造函数,在调用 Shape.new() 创建 Shape 对象实例时会自动执行
011. function Shape:ctor(shapeName)
012.     self.shapeName = shapeName
013.     printf("Shape:ctor(%s)", self.shapeName)
014. end
015.   
016. -- 为 Shape 定义个名为 draw() 的方法
017. function Shape:draw()
018.     printf("draw %s", self.shapeName)
019. end
020.   
021. --
022.   
023. -- Circle 是 Shape 的继承类
024. local Circle = class("Circle", Shape)
025.   
026. function Circle:ctor()
027.     -- 如果继承类覆盖了 ctor() 构造函数,那么必须手动调用父类构造函数
028.     -- 类名.super 可以访问指定类的父类
029.     Circle.super.ctor(self, "circle")
030.     self.radius = 100
031. end
032.   
033. function Circle:setRadius(radius)
034.     self.radius = radius
035. end
036.   
037. -- 覆盖父类的同名方法
038. function Circle:draw()
039.     printf("draw %s, raidus = %0.2f", self.shapeName, self.raidus)
040. end
041.   
042. --
043.   
044. local Rectangle = class("Rectangle", Shape)
045.   
046. function Rectangle:ctor()
047.     Rectangle.super.ctor(self, "rectangle")
048. end
049.   
050. --
051.   
052. local circle = Circle.new()             -- 输出: Shape:ctor(circle)
053. circle:setRaidus(200)
054. circle:draw()                           -- 输出: draw circle, radius = 200.00
055.   
056. local rectangle = Rectangle.new()       -- 输出: Shape:ctor(rectangle)
057. rectangle:draw()                        -- 输出: draw rectangle
058.   
059. ~~~
060.   
061. ### 高级用法
062.   
063. class() 除了定义纯 Lua 类之外,还可以从 C++ 对象继承类。
064.   
065. 比如需要创建一个工具栏,并在添加按钮时自动排列已有的按钮,那么我们可以使用如下的代码:
066.   
067. ~~~ lua
068.   
069. -- 从 cc.Node 对象派生 Toolbar 类,该类具有 cc.Node 的所有属性和行为
070. local Toolbar = class("Toolbar", function()
071.     return display.newNode() -- 返回一个 cc.Node 对象
072. end)
073.   
074. -- 构造函数
075. function Toolbar:ctor()
076.     self.buttons = {} -- 用一个 table 来记录所有的按钮
077. end
078.   
079. -- 添加一个按钮,并且自动设置按钮位置
080. function Toolbar:addButton(button)
081.     -- 将按钮对象加入 table
082.     self.buttons[#self.buttons + 1] = button
083.   
084.     -- 添加按钮对象到 cc.Node 中,以便显示该按钮
085.     -- 因为 Toolbar 是从 cc.Node 继承的,所以可以使用 addChild() 方法
086.     self:addChild(button)
087.   
088.     -- 按照按钮数量,调整所有按钮的位置
089.     local x = 0
090.     for _, button in ipairs(self.buttons) do
091.         button:setPosition(x, 0)
092.         -- 依次排列按钮,每个按钮之间间隔 10 
093.         x = x + button:getContentSize().width + 10
094.     end
095. end
096.   
097. ~~~
098.   
099. class() 的这种用法让我们可以在 C++ 对象基础上任意扩展行为。
100.   
101. 既然是继承,自然就可以覆盖 C++ 对象的方法:
102.   
103. ~~~ lua
104.   
105. function Toolbar:setPosition(x, y)
106.     -- 由于在 Toolbar 继承类中覆盖了 cc.Node 对象的 setPosition() 方法
107.     -- 所以我们要用以下形式才能调用到 cc.Node 原本的 setPosition() 方法
108.     getmetatable(self).setPosition(self, x, y)
109.   
110.     printf("x = %0.2f, y = %0.2f", x, y)
111. end
112.   
113. ~~~
114.   
115. **注意:** Lua 继承类覆盖的方法并不能从 C++ 调用到。也就是说通过 C++ 代码调用这个 cc.Node 对象的 setPosition() 方法时,并不会执行我们在 Lua 中定义的 Toolbar:setPosition() 方法。
116.   
117. @param string classname 类名
118. @param [mixed super] 父类或者创建对象实例的函数
119.   
120. @return table
121.   
122. ]]
123. function class(classname, super)
124.     local superType = type(super)
125.     local cls
126.   
127.     if superType ~= "function" and superType ~= "table" then
128.         superType = nil
129.         super = nil
130.     end
131.   
132.     if superType == "function" or (super and super.__ctype == 1) then
133.         -- inherited from native C++ Object
134.         cls = {}
135.   
136.         if superType == "table" then
137.             -- copy fields from super
138.             for k,v in pairs(superdo cls[k] = v end
139.             cls.__create = super.__create
140.             cls.super    super
141.         else
142.             cls.__create = super
143.             cls.ctor = function() end
144.         end
145.   
146.         cls.__cname = classname
147.         cls.__ctype = 1
148.   
149.         function cls.new(...)
150.             local instance = cls.__create(...)
151.             -- copy fields from class to native object
152.             for k,v in pairs(cls) do instance[k] = v end
153.             instance.class = cls
154.             instance:ctor(...)
155.             return instance
156.         end
157.   
158.     else
159.         -- inherited from Lua Object
160.         if super then
161.             cls = {}
162.             setmetatable(cls, {__index = super})
163.             cls.super super
164.         else
165.             cls = {ctor = function() end}
166.         end
167.   
168.         cls.__cname = classname
169.         cls.__ctype = 2 -- lua
170.         cls.__index = cls
171.   
172.         function cls.new(...)
173.             local instance = setmetatable({}, cls)
174.             instance.class = cls
175.             instance:ctor(...)
176.             return instance
177.         end
178.     end
179.   
180.     return cls
181. end

传入是一个父类的话,会调用cls.new函数,然后创建实例,调用ctor构造函数

 

6. 调用一个实例:

假设派生自一个cocos的类 Sprite

 

01. -- class可以传12个参数
02. -- @param 类名,内部做记录而已,一般和返回的类名一致即可
03. -- @param 如果传参数2 使用当前函数作为构造函数 如果没参数2 默认的构造函数
04. local Box = class("Box", function(filename)
05.         return cc.Sprite:create(filename)
06.     end)
07.   
08. -- 设置元彪 更改元表默认的元方法
09. -- 访问table中不存在的字段时,解释器查找__index的元方法,否则返回nil
10. -- 多用于继承 http://blog.csdn.net/q277055799/article/details/8463883
11. Box.__index = Box
12. Box.isDead = false      --定义属性
13.   
14. -- 构造函数(会自动调用)
15. -- 外界构造时可以传任意参数XXX.new(...)
16. function Box:ctor(pic_path)
17.     local function onNodeEvent(event)
18.         if "enter" == event then
19.             Box:onEnter(pic_path)
20.         elseif "exit" == event then
21.             Box:onExit()
22.         end
23.     end
24.   
25.     self:registerScriptHandler(onNodeEvent)
26.   
27.     local function onUpdate()
28.   
29.     end
30.     self:scheduleUpdateWithPriorityLua(onUpdate, 0)
31.   
32. end
33.   
34. function Box:onEnter(pic_path)
35. end
36.   
37. function Box:onExit()
38. end
39.   
40.   
41. function Box.create(parent, position)
42.     local box = Box.New("data/box.png")
43.     parent:addChild(box)
44.     return box
45. end
46.   
47. return Box

如果是一个table,可以直接使用

 

 

1. local Bomb = class("Bomb")

 

7.我们常见cocos2dx的例子中有大量的extend和tolua.getpeer用法如下:

 

01. local TimelineTestScene = class("TimelineTestScene")
02. TimelineTestScene.__index = TimelineTestScene
03.   
04. function TimelineTestScene.extend(target)
05.     local t = tolua.getpeer(target)
06.     if not t then
07.         t = {}
08.         tolua.setpeer(target, t)
09.     end
10.     setmetatable(t, TimelineTestScene)
11.     return target
12. end
13.   
14. function TimelineTestScene.create()
15.     local scene = TimelineTestScene.extend(cc.Scene:create())
16.     return scene   
17. end

 

用的时tolua.getpeer,其实它的功能就相当于调用了class,所以请远离extend吧

 

1. local TimelineTestScene = class("TimelineTestScene", cc.Scene)
2. TimelineTestScene.__index = TimelineTestScene
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值