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
原创粉丝点击