middleclass.lua分析
来源:互联网 发布:sql语句查询数据库表 编辑:程序博客网 时间:2024/06/03 21:28
-- middleclass.lua - v2.0 (2011-09)--记录所有由这个体系建立的表,用来记录创建的所有类表local _classes = setmetatable({}, {__mode = "k"})--类元表字典 klass为传入的表 即代表一个类 用来给这个klass类表的static表建立访问关系,关系如下注释local function _setClassDictionariesMetatables(klass) local dict = klass.__instanceDict dict.__index = dict local super = klass.super if super then --有父类表时 --得到父类表的static --先把当前klass表的__instanceDict表的元表设为klass的父类表的__instanceDict表(由上知道__instanceDict表有__index字段, 又指向其自身) --意为:访问当前表的__instanceDict表时找不到,就到父类表的__instanceDict表中去找 --同样把当前klass表的static表设置一个元表,该元表的__index方法如下 --意为:访问当前klass表的static表时,如果直接找不到,会优先到其__instanceDict表去找(由上,也找不到到其父类的__instanceDict表总找) --再找不到,到其父类的static表里找 local superStatic = super.static setmetatable(dict, super.__instanceDict) setmetatable(klass.static, { __index = function(_,k) return dict[k] or superStatic[k] end }) else --没有父类表时 --给这个klass表的内部的static表设置一个元表 --元表的__index字段为一个函数(table, key), table为哑元,所以这个函数接受了那个key --函数从这个klass表的内部的__instanceDict表中获取,而__instanceDict表的__index字段又指向其自身 --(注意:并不是其元表的index,也就是仅仅是为了能把__instanceDict也能作为一个接受值得元表用) --综上:也就是访问这个klass的static表时,如果没有就到其__instanceDict表中去找 setmetatable(klass.static, { __index = function(_,k) return dict[k] end }) endend--klass为一个表 给这个klass创建元表,即给其建立访问关系local function _setClassMetatable(klass) --[[ 设__tosring函数,为class..name 方便打印 设__index为其自身的static表,即访问自己没有就找自己的static表 设__newindex为自己的__instanceDict,即赋值新元素值时,给自己的__instanceDict赋值而不是给自己 设__call,表示以函数形式调用这个表时的操作 即:实际是调用自己的new,模仿了构造函数的形式 --]] setmetatable(klass, { __tostring = function() return "class " .. klass.name end, __index = klass.static, __newindex = klass.__instanceDict, __call = function(self, ...) return self:new(...) end })end--name新建类表的类名 super父类表local function _createClass(name, super) --构造表 等价于["name"] = name local klass = { name = name, super = super, static = {}, __mixins = {}, __instanceDict={} } klass.subclasses = setmetatable({}, {__mode = "k"}) --设置klass的subclasses表的元表 _setClassDictionariesMetatables(klass)--设置自己的static表的访问关系 _setClassMetatable(klass)--设置自己的访问关系 _classes[klass] = true--以这个类表作为键,在__Classes里设为true,应该时用来记录所有的创建的类表,同时增加一个引用,使其不会被回收 return klassend--传入表和元方法名字字符串 返回一个函数 注意返回的时一个函数 而不是函数的值local function _createLookupMetamethod(klass, name) return function(...) --的到其父类的元方法,然后调用并把值传递出去 local method = klass.super[name] assert( type(method)=='function', tostring(klass) .. " doesn't implement metamethod '" .. name .. "'" ) return method(...) endend--给klass建立元方法 注意:调用这个函数时已经建立访问关系,所有元方法时建立在自己的__instanceDict表里的local function _setClassMetamethods(klass) --遍历元方法表,就是下面自己建立的那个表,里面都是元方法字符串 for _,m in ipairs(klass.__metamethods) do --对于每一个元方法名字,在自己表内建立对应的函数,函数功能就是调用父类的相应同名元方法,然后返回值 klass[m]= _createLookupMetamethod(klass, m) endend--传入一个表,和其父表 设置这个表的initialize函数--注意:调用这个函数时,已经建立访问关系,所以这个函数是放在自己的__instanceDict表里的local function _setDefaultInitializeMethod(klass, super) --这个表的初始化函数就是调用其父类表的初始化函数 klass.initialize = function(instance, ...) return super.initialize(instance, ...) endend--用于把mixin表混合到klass表中local function _includeMixin(klass, mixin) --确保mixin为表 assert(type(mixin)=='table', "mixin must be a table") --遍历mixin表里的所有成员,把不是include和static的成员都加到klass里面 for name,method in pairs(mixin) do if name ~= "included" and name ~= "static" then klass[name] = method end end --如果mixin有static表 --遍历mixin的static表,把其中的所有成员放到klass的static表中 if mixin.static then for name,method in pairs(mixin.static) do klass.static[name] = method end end --如果mixin的include字段为函数,调用 if type(mixin.included)=="function" then mixin:included(klass) end klass.__mixins[mixin] = true--mixins表记录下来合起混合的end--Object表的建立,作为一个全局的类表Object = _createClass("Object", nil)--static的__metamethods 里面都是字符串名 来标示元方法,子类表创建时,用来遍历创建相应函数Object.static.__metamethods = { '__add', '__call', '__concat', '__div', '__le', '__lt', '__mod', '__mul', '__pow', '__sub', '__tostring', '__unm' }--self传入调用的那个类表,根据这个类表创建一个对象表function Object.static:allocate() --确保self为体系中创建的表,self为调用时的那个表,一直递归找上来的那个表 assert(_classes[self], "Make sure that you are using 'Class:allocate' instead of 'Class.allocate'") --新建一个对象表,这个对象表的class键指向其类表self,且这个对象表的元表为其类表的__instanceDict字段 return setmetatable({ class = self }, self.__instanceDict)end--表示用这个类表生成一个对象function Object.static:new(...) local instance = self:allocate()--根据这个类表创建一个对象表 instance:initialize(...)--调用这个新建的对象表的调用initialize函数 return instance--返回这个对象表end--构造一个Object的子类表function Object.static:subclass(name) --第一个assert 保证有self传进来 --self就为实际的那个表,不一定是Object表,可能是Object的子类表,因为子类表没有subclass函数时,会到父类表的static中找,当前这个父类表也不一定是Object --父类表再没有递归上来,直到到这个Object的这个函数来,但此时self是那个初始调用的那个表 assert(_classes[self], "Make sure that you are using 'Class:subclass' instead of 'Class.subclass'") assert(type(name) == "string", "You must provide a name(string) for your class") local subclass = _createClass(name, self)--创建一个新表,以self为父表 会建立subclass和slef的访问关系,并把subclass记录在全局的_Classes --注意:由于上面已经建立了读取和设置关系,所以下面新加的方法都放在表的__instanceDict表里,而不是自身里 _setClassMetamethods(subclass)--在新表里面建立上面列的元方法,每个元方法对应功能就是调用父类的元方法 _setDefaultInitializeMethod(subclass, self)--设置新建的子类表的初始化函数,就是调用父类的初始化函数 self.subclasses[subclass] = true--在父类表的subclasses表中记录下这个子类表 self:subclassed(subclass)--调用父类表的subclassed函数 return subclass--创建完成,返回这个新建的表end--subclassed函数,也是空函数,暂时不知道何意义,难道为了扩展统计???function Object.static:subclassed(other) end--把参数传递的所有参数(都为表),混合近self中去function Object.static:include( ... ) assert(_classes[self], "Make sure you that you are using 'Class:include' instead of 'Class.include'") --遍历参数的,把每个混合井self中去,然后返回self for _,mixin in ipairs({...}) do _includeMixin(self, mixin) end return selfend--初始化函数,Object的初始化函数就为空function Object:initialize() endfunction Object:__tostring() return "instance of " .. tostring(self.class) end--声明一个类 name类名 super父类名 ...构造参数--注意着只是定义类,用来在这个体系中创建每个表自己的关系,来构造成类继承的结构function class(name, super, ...) super = super or Object --未指定父类 就用Object return super:subclass(name, ...)end--判断obj是否由aClass生成的表function instanceOf(aClass, obj) --若aClass不是这个体系中的,或obj根本就不是表,或?? if not _classes[aClass] or type(obj) ~= 'table' or not _classes[obj.class] then return false end if obj.class == aClass then return true end return subclassOf(aClass, obj.class)end--判断other是否为aClass的父类function subclassOf(other, aClass) --如果other或cClass有一不是这个体系建立的表,或aClass没有super父表,则返回false if not _classes[aClass] or not _classes[other] or aClass.super == nil then return false end --否则要么aClass的直接父类就是other,要么递归上去,看aClass的父类的父类是否是other return aClass.super == other or subclassOf(other, aClass.super)endfunction includes(mixin, aClass) if not _classes[aClass] then return false end if aClass.__mixins[mixin] then return true end return includes(mixin, aClass.super)end--[[总结体系成员 当前文件一个local _classes表,所有在这个体系中创建的类表,都会记录在其中 全局的一个OBject类表,作为基类 OBject的函数时定义在其static表内的 分为类表和对象表 类表时由上面的class函数来建立,描述的是一个类,class创建类表时还能指定父类,来建立类表间的继承关系 对象表,由一个类表的调用new函数得到,会新建一个表,并调用其初始化函数,真正使用的是对象表 由Class函数创建可以看出,这是一个单继承体系模型 Mixin?意义待分析体系中每个类表成员和作用 name 字符串,表示这个类的名字 super 表,指向这个表的父类表 static 表,静态功能表,实现了建立体系的基础函数,除了Object外,其他默认都是空的 __mixins 表,记录所有和这个表混合的表 __instanceDict 表,类实现字典,放置所有给当前类表定义的函数和变量 subclasses 表,以子类表作为键,记录这个表的所有子类表类表的读取和设置关系 设当前类表为A,A的直接基类表为B,B的直接基类表为C,以此类推设最上层为Z 联通属性如下 1 每个类表自身和其static表是__index联通的 2 每个类表自身和其__instanceDict表是__newindex联通的 3 每个类表的static表和其自身的__instanceDict表是__index联通的 4 每个类表的__instanceDict表和其直接基类表的__instanceDict表是__index联通的 访问A时 读取A 若A自身没有,到A的static表中读(1),也没有到A的__instanceDict表中读(3),也没有递归往直接基类的__instanceDict表读(4),递归到最上Z的__instanceDict表(4) 也没有,此时到A直接父类B的static表中找,再没有到B的__instanceDict表找(3),然后同上递归到最上Z的__instanceDict表(4)(即,这里实际为不必要的) 此时寻找结束 所以有 5 读取顺序,查找自己,自己的static表,自己的__instanceDict表,继承体系中所有基类的__instanceDict表,直接基类的static表 设置A 若A自身没有,到A的__instanceDict表去设置(2),然后结束 所以有 6 设置顺序,查找自己,和自己的__instanceDict表 所有类表不会在自身表内设置新值,新值是保存在自己的__instanceDict表中建立初始化和元方法函数(注意:这些函数在类表的__instanceDict里)(OBject的initialize方法也在其自身的__instanceDict表里) 遍历元方法名,在自己表内建立对应键的函数,函数功能就是调用父类的相应同名元方法,然后返回值 如上访问关系建立后,给新类表,自身一个initialize函数,函数功能就是调用其父类的initialize函数 如上设置属性可知:是为了给表定义这些函数时,是直接在表里,不会到其__instanceDict表去设置 所以有 7 Object的static表里实现了基础的体系函数,而其他体系中的表默认static里是空的 除了体系中构建时给你类表里添加东西外,其他所有你新加的东西都会放在自己的__instanceDict表里,除非你显示指定位置对象表和类表的关系 对象表通过体系中相应的类表调用new函数实现 会新建一个空表,给空表一个键class指向创建他的那个类表,同时把这个类表的__instanceDict表设置为这个新建对象表的元表 所以: 新建的对象表,默认自身只会含有一个键class指向创建他的那个类表,新建对象表的元表是创建他的那个类表的__instanceDict表 读取, 读取这个对象表,自己没有就到class指向的类表的的__instanceDict表中找,然后递归向上找__instanceDict表(4) 设置, 设置只会设置自己 对象表一般不用设置,且设置的话不会影响到其类表,只是在对象表自身里面类体系实现 定义类时 使用class和父类建立访问关系,并在自己的__instanceDict里,建立默认的initialize函数和元方法函数 所有非明确指定的定义的新函数和变量都放在自己的__instanceDict表里 新建对象的初始化 创建对象时,由类表new,先创建一个对象表,然后以这个对象表去调用initialize,对象表实际没有initialize函数,所以访问的是类表的__instanceDict里找 而所有类的实现方法都是在__instanceDict表里的,所以就是以这个对象表作为self去调用类表的initialize函数,形成初始化 方法的继承 访问对象表方法时,没有到其类表的__instanceDict里找,然后递归向上__instanceDict(找),所以一个对象表,如果自己没有,就能用其所有基类表 的方法和变量 修改的屏蔽 对类表进行设置,仅仅在自己的__instanceDict表里,设置,不会影响到父类表 对对象表进行设置,仅仅是对对象表自己进行设置,不会影响到其类表 (这里有个迷惑,因为类和对象都是由表来模仿的,这里的对象还是表,还可以给自己添加变量,在C++模型中确不会有这个概念) 方法的覆盖 由于是由下到上找,找到即停,所以子类表的方法和变量会覆盖,其父类表的方法和变量 方法的重载 如果在同一层次找到多个同名的函数,此时???Mixin作用 用来模仿多继承吗?待分析?使用--]]
0 0
- middleclass.lua分析
- Lua middleclass(v4.1) 解析
- lua middleclass 的一个要注意的问题,静态属性
- middleclass源码阅读笔记
- [cocos2dx-lua]"Hello Lua"分析
- common.lua文件分析
- Lua源码分析(1)
- Lua 源码分析(一)
- Lua 源文件分析
- Lua module机制分析
- lua源码分析文档
- Lua mem 分析
- lua源代码文件分析
- Lua词法分析总结
- lua源代码文件分析
- Lua虚拟机分析之一
- lua gc分析(一)
- lua GC分析
- C# VBRegExp10
- Mac OS X中Android Kernel的下载方法
- S5PV210(TQ210)学习笔记——LCD驱动编写
- 阿里云安装mysql
- 敏捷开发
- middleclass.lua分析
- linux-2.6.32在mini2440开发板上移植(16)之LED 驱动程序移植
- [C++11] 对不同类别不定参数的ForEach
- linux-2.6.32在mini2440开发板上移植----- RTC移植
- Java Details: mod and %
- linux-2.6.32在mini2440开发板上移植 ---按键驱动程序移植
- demo1,DOM元素-careteElement-appendChild-insertBefore
- linux-2.6.32在mini2440开发板上移植---移植I2C-EEPROM 驱动
- linux-2.6.32在mini2440开发板上移植--移植DM9000 网卡驱动