middleclass.lua分析

-- 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 })
  end
end

--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 klass
end

--传入表和元方法名字字符串   返回一个函数   注意返回的时一个函数   而不是函数的值
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(...)
  end
end

--给klass建立元方法   注意:调用这个函数时已经建立访问关系,所有元方法时建立在自己的__instanceDict表里的
local function _setClassMetamethods(klass)
  --遍历元方法表,就是下面自己建立的那个表,里面都是元方法字符串
  for _,m in ipairs(klass.__metamethods) do
    --对于每一个元方法名字,在自己表内建立对应的函数,函数功能就是调用父类的相应同名元方法,然后返回值
    klass[m]= _createLookupMetamethod(klass, m)
  end
end

--传入一个表,和其父表   设置这个表的initialize函数
--注意:调用这个函数时,已经建立访问关系,所以这个函数是放在自己的__instanceDict表里的
local function _setDefaultInitializeMethod(klass, super)
  --这个表的初始化函数就是调用其父类表的初始化函数
  klass.initialize = function(instance, ...)
    return super.initialize(instance, ...)
  end
end

--用于把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 self
end

--初始化函数,Object的初始化函数就为空
function Object:initialize() end

function 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)
end

function 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作用
  用来模仿多继承吗?待分析?




使用


--]]

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值