格物致知,诚意正心,修身齐家治国平天下-----《大学》
所以一切的开始是格物致知,研究事物,才能获得知识。尤其对于我等程序员。最近在学习Quick-cocos2d-x,看到可以用class函数定义类,当然此函数不是lua提供的。虽然知道怎么用它定义类,但是如果不知道它到底做了什么,用起来总觉得不是那么踏实。所以花了些时间研究了下。总算大致明白了(自己认为的明白):
function class(classname,super) local superType = type(super) local cls if superType ~= "function" and superType ~= "table" then superType = nil super = nil end if superType == "function" or (super and super.__ctype == 1) then -- inherited from native C++ Object 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 --rewrite this if need 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 else -- inherited from Lua Object if super then 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 end return cls end从总体上看,这个函数返回一个tabel,其父类(super)可能是c++中导出的类,也可能是lua中的原生的类。那么怎么判断呢?方法就是,根据父类的类型,if superType == "function" or (super and super.__ctype == 1)代表父类是来自c++。那在这个if下的if superType == "table" then...又是什么意思呢?我主要就是被这句给卡住了,后来加上些调试信息,发现这个代表是间接继承自c++,即父类是tabel,但是祖父或者老祖宗是c++的类。既然是表就要复制父类表的内容啊,所以就
for k,v in pairs(super) do cls[k] = v end cls.__create = super.__create --注释掉也没发现问题 cls.super = super看到我加的汉字的注释了吧(很明显),因为在直接继承c++类的时候已经把cls.__create = super了(见下面else的代码),那么间接继承时又有for k,v in pairs(super) do cls[k] = v end,这句就必然会把父类的__create的键值对赋给子类,所以子类的__create的值不然是第一个继承c++类的时候的super的那个函数。(说的不是很清楚,但这不是主要的,主要是要了解它的框架。正所谓好读书,不求甚解,每有会意,便欣然忘食)
else cls.__create = super cls.ctor = function() end --rewrite this if need end然后还有这一句
cls.__ctype = 1这个就是判断是不是继承自c++类的依据。
接下来就是总的继承自c++的类的new方法了
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第一句cls.__create() 就是创造出c++的部分,因为cls.__create()最终是 cls.__create = super,然后是复制其他部分。最后又调用了instance:ctor(...),所以当用此类的new方法创造一个实例的时候,你的类的ctor()函数就会被调用,不用你自己调用,相当于构造函数。
接下来是直接继承自lua对象的,
if super then setMetatable(cls,{__index = super}) cls.super = super主要就是利用了元表的特点,如果在一个tabel中查找一个键,如果存在就直接返回对应的值,如果不存在就看此tabel是否设有元表,如果有,再看元表有没有__index 这个键(元方法),如果有就从__index所对应的值上找,而这里__index就是父类。这样,结果就是,如果这个子类没有的键就去父类里找。很像c++吧。
这个new()方法就不分析了,差不多啦,只要懂lua的元表就能懂。上学时最怕写作文了,提笔忘字。