cocos2dx中有关于lua类的实现,见cocos源码 framework/functions。
先讲一部分比较难理解的:
function class(classname, super)
local cls
-- inherited from Lua Object
if super then
cls = {}
setmetatable(cls, {__index = super})
cls.super = super
else
cls = {ctor = function() end}
end
cls.__cname = classname
cls.__ctype = 2 -- lua
cls.__index = cls
function cls.new(...)
local instance = setmetatable({}, cls)
instance.class = cls
instance:ctor(...)
return instance
end
return cls
end
主要涉及lua的一个用法——元表。通俗的讲,假设A和B都是table,B里面有键值对,里面有b,A里面没有,想在A里面找b会找不到,如果setmetatable(A,B),则会去看B,看B有没有设置__index字段,如果有就会去B里面找键值对。
对于类来讲,假设有类A,当调用实例的方法a时,发现找不到,因为虽然A中有方法,但是实例中没有添加该方法,由于上面 local instance = setmetatable({}, cls),实例就会去查看cls即类A,而通过cls.__index = cls,A有把自己设置为__index,查A的时候就会去查它本身所有的键值对,即它所有的成员,方法a就被找到了。
另一种情况,如果类A的实例想调用方法s,而s是在类A的基类类S中定义的,A中并没有定义,由于A定义的时候有setmetatable(cls, {__index = super}),则找方法s的时候会去找A的super,即S,且super设置了__index,也可被找到,继承就实现了。
再讲另外一部分:
if superType == "function" or (super and super.__ctype == 1) then
这句是指如果 function class(classname, super) 里的super是函数,或者是C++类,则进行不同于上面的处理(上面是指lua的类和继承),代码如下:
cls = {}
if superType == "table" then
-- copy fields from super
for k,v in pairs(super) do cls[k] = v end
cls.__create = super.__create
cls.super = super
else
cls.__create = super
cls.ctor = function() end
end
cls.__cname = classname
cls.__ctype = 1
function cls.new(...)
local instance = cls.__create(...)
-- copy fields from class to native object
for k,v in pairs(cls) do instance[k] = v end
instance.class = cls
instance:ctor(...)
return instance
end
其实这里比较好理解了,如果继承自table,需要把基类所有成员复制过来,如果super参数是个函数,则需要在函数中通过基类创建子类。而在cls.new(…)函数里面,实例化时也要拷贝所有的成员,这样父类的成员就可以为子类的实例所用了,cocos里面找了两个例子:
local UIButton = class("UIButton", function()
return display.newNode()
end)
local UIButton = import(".UIButton")
local UIPushButton = class("UIPushButton", UIButton)
附一下cocos注释里面提供的示例:
-- 定义名为 Shape 的基础类
local Shape = class("Shape")
-- ctor() 是类的构造函数,在调用 Shape.new() 创建 Shape 对象实例时会自动执行
function Shape:ctor(shapeName)
self.shapeName = shapeName
printf("Shape:ctor(%s)", self.shapeName)
end
-- 为 Shape 定义个名为 draw() 的方法
function Shape:draw()
printf("draw %s", self.shapeName)
end
-- Circle 是 Shape 的继承类
local Circle = class("Circle", Shape)
function Circle:ctor()
-- 如果继承类覆盖了 ctor() 构造函数,那么必须手动调用父类构造函数
-- 类名.super 可以访问指定类的父类
Circle.super.ctor(self, "circle")
self.radius = 100
end
function Circle:setRadius(radius)
self.radius = radius
end
-- 覆盖父类的同名方法
function Circle:draw()
printf("draw %s, raidus = %0.2f", self.shapeName, self.raidus)
end
--
local Rectangle = class("Rectangle", Shape)
function Rectangle:ctor()
Rectangle.super.ctor(self, "rectangle")
end
--
local circle = Circle.new() -- 输出: Shape:ctor(circle)
circle:setRaidus(200)
circle:draw() -- 输出: draw circle, radius = 200.00
local rectangle = Rectangle.new() -- 输出: Shape:ctor(rectangle)
rectangle:draw() -- 输出: draw rectangle