cocos2dx lua (伪)面向对象理解与实战应用
面向对象
>> 把一组数据结构和处理它们的方法组成对象(object),把相同行为的对象归纳为类(class)
>> 通过类的封装(encapsulation)隐藏内部细节
>> 通过继承(inheritance)实现类的特化(specialization)/泛化(generalization)
>> 通过多态(polymorphism)实现基于对象类型的动态分派(dynamic dispatch)
1.lua中的类
lua中其实是没有类的,有的只是表(table),而类之间的继承也就是将父类的表连到了一起,派生类中没有找到的属性和方法就通过元表查找父类
2.lua中类的属性
classA = {width =10, height=10}
classA={}
classA.width=10
classA.height=10
两种方法都可以,通过点self.width统一调用
3.类方法
[cpp] view plaincopy
function Box:collsion()
– 默认第一个参数隐藏传递self,可以通过self.xxx 调用属性和方法
end
function Box.create(self)
–必须手动传递参数self,否则无法用self.xxx调用属性和方法
end
4.类与元表的用法
- lua查找一个表元素时的规则,其实就是如下3个步骤:
- 4.1.在表中查找,如果找到,返回该元素,找不到则继续
- 4.2.判断该表是否有元表,如果没有元表,返回nil,有元表则继续
- 4.3.判断元表有没有index方法,如果index方法为nil,则返回nil;如果index方法是一个表,则重复1、2、3;如果index方法是一个函数,则返回该函数的返回值
在Lua中,函数的声明和调用可以用”:”和”.”,属性调用全部用点”.”
我们知道,对象由属性和方法组成。LUA中最基本的结构是table,所以需要用table来描述对象的属性。
lua中的function可以用来表示方法。那么LUA中的类可以通过table + function模拟出来。
至于继承,可以通过metetable模拟出来(不推荐用,只模拟最基本的对象大部分时间够用了)。
Lua中的表不仅在某种意义上是一种对象。像对象一样,表也有状态(成员变量);也有与对象的值独立的本性,特别是拥有两个不同值的对象(table)代表两个不同的对象;一个对象在不同的时候也可以有不同的值,但他始终是一个对象;与对象类似,表的生命周期与其由什么创建、在哪创建没有关系。
1. 初步面向对象
ObjectData = {balance = 0}
function ObjectData.count( v )
– body
print("value is :", v)
end
a = ObjectData
a.count("iCocos")
– value is : iCocos
2. 面向对象模拟
ObjectData = {balance = 100}
function ObjectData.count( self, v )
self.balance = self.balance + v
print("value is :", v, self.balance)
end
a = ObjectData
a.count(a, 99) – 传递self
– value is : 99 199
a:count(99) – 不传self,直接把a作为self传递进入,
– value is : 99 298
Lua中的继承
先来定义一个基类,
使用前面讲的setmetatable来实现基本的元表
local _M = {}
function _M:new(name)
return setmetatable({ name = name}, { __index = _M })
end
function _M:show()
print(self.name .. ": show in parent:")
end
function _M:hello(arg)
print(self.name .. ": hello in parent:" .. tostring(arg))
end
return _M
子类的实现
local parent = require("parent")
local _M = {}
function _M:new()
local obj = parent:new("the child")
local super_mt = getmetatable(obj)
– 当方法在子类中查询不到时,再去父类中去查找。
setmetatable(_M, super_mt)
– 这样设置后,可以通过self.super.method(self, …) 调用父类的已被覆盖的方法。
obj.super = setmetatable({}, super_mt)
return setmetatable(obj, { __index = _M })
end
– 覆盖父类的方法。
function _M:hello()
– 只能使用这种方法调用基类的方法。
self.super.hello(self, "call from child")
print(tostring(self.name) … ": hello in child")
end
return _M
test.lua (使用)
– local parent = require("parent")
local child = require("child")
local c = child:new()
– 从parent继承的show方法
c:show()
– child自己的方法。
c:hello()
执行lua test.lua 后 输出:
the child: show in parent:
the child: hello in parent:call from child
the child: hello in child
- 可以看到:
- show是继承了父类的方法。
- hello是由子类覆盖了,并且在hello中调用了父类的hello方法。