Lua middleclass(v4.1) 解析
来源:互联网 发布:淘宝官方下载 编辑:程序博客网 时间:2024/05/22 06:21
A simple OOP library for Lua. It has inheritance, metamethods (operators), class variables and weak mixin support.
https://github.com/kikito/middleclass
函数功能解析
1. _createClasss(aClass, super)
返回默认的表
local dict = {} dict.__index = dict local aClass = { name = name, super = super, static = {}, __instanceDict = dict, __declaredMethods = {}, subclasses = setmetatable({}, {__mode='k'}) }
创建一个table,包含下列属性:
* name 类名
* super 父类的table
* static 静态表
* __instanceDict 存放类定义的属性和函数(包含父类)
* __decaredMethod (当前类声明的方法,不包含父类)
* subclasses 子类表, 使用弱引用
if super then setmetatable(aClass.static, { __index = function(_,k) return rawget(dict,k) or super.static[k] end }) else setmetatable(aClass.static, { __index = function(_,k) return rawget(dict,k) end }) end
设置static表的元表为 __index = __instanceDict(或者super.static)
setmetatable(aClass, { __index = aClass.static, __tostring = _tostring, __call = _call, __newindex = _declareInstanceMethod })
设置类的元表:__index 为 static, __tostring => 默认tostring,
_call =>调用static.new(), __newindex => _declareInstanceMethod
2. _includeMixin(aClass, mixin)
将一张表合并到另一张表中
for name,method in pairs(mixin) do if name ~= "included" and name ~= "static" then aClass[name] = method end end
- 除了”included”和”static”,将mixin中的域全部赋值到aClass中(覆盖)
for name,method in pairs(mixin.static or {}) do aClass.static[name] = method end
- 将mixin.static中的域,赋值到aClass.static中
if type(mixin.included)=="function" then mixin:included(aClass) end
- 如果mixin包含included方法,则调用mixin的included方法,参数为aClass
3. DefaultMixin
* 默认合并表,创建类时自动添加到类中*
提供如下方法:
* __tostring 默认tostring方法
* initialize 初始化方法 类似于构造函数
isInstanceOf = function(self, aClass) return type(aClass) == 'table' and (aClass == self.class or self.class:isSubclassOf(aClass)) end,
- isInstanceOf 判断是否是某个类的实例
为static添加方法:
allocate = function(self) assert(type(self) == 'table', "Make sure that you are using 'Class:allocate' instead of 'Class.allocate'") return setmetatable({ class = self }, self.__instanceDict) end,
- allocate 创建一个实例表
- 添加class属性,指向类表
- 将类表的__instanceDict设置为元表
new = function(self, ...) assert(type(self) == 'table', "Make sure that you are using 'Class:new' instead of 'Class.new'") local instance = self:allocate() instance:initialize(...) return instance end,
new 通过allocate创建表,并调用initialize方法
subclassed 创建子类后的回调
subclass = function(self, name) assert(type(self) == 'table', "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) for methodName, f in pairs(self.__instanceDict) do _propagateInstanceMethod(subclass, methodName, f) end subclass.initialize = function(instance, ...) return self.initialize(instance, ...) end self.subclasses[subclass] = true self:subclassed(subclass) return subclass end,
- subclass 为类添加一个指定名字的子类,并返回子类
- 创建指定名字的类,父类为自己
- 将父类的__instanceDict中的所有域,复制到子类中
- 子类的initialize 默认调用父类的initialize
- 在自己的subclass索引中,添加子类的索引
- 调用自己的subclassed方法,参数为子类
isSubclassOf = function(self, other) return type(other) == 'table' and type(self.super) == 'table' and ( self.super == other or self.super:isSubclassOf(other) ) end,
- isSubclassOf 是否是指定类的子类
include = function(self, ...) assert(type(self) == 'table', "Make sure you that you are using 'Class:include' instead of 'Class.include'") for _,mixin in ipairs({...}) do _includeMixin(self, mixin) end return self end
- include 将参数合并到本类中
4. _declareInstanceMethod(aClass, name, f)
在类中添加声明方法和属性
local function _declareInstanceMethod(aClass, name, f) aClass.__declaredMethods[name] = f if f == nil and aClass.super then f = aClass.super.__instanceDict[name] end _propagateInstanceMethod(aClass, name, f)end
- 注册到__declaredMethods
- 如果f为nil,则去父类取该字段
- 将域添加到子类中
5. _propagateInstanceMethod(aClass, name, f)
添加域到表中,并添加到所有的子类中,相当于继承
local function _propagateInstanceMethod(aClass, name, f) f = name == "__index" and _createIndexWrapper(aClass, f) or f aClass.__instanceDict[name] = f for subclass in pairs(aClass.subclasses) do if rawget(subclass.__declaredMethods, name) == nil then _propagateInstanceMethod(subclass, name, f) end endend
- 如果name = __index, 调用_createIndexWrapper
- 将f添加到aClass.__instanceDict[name]中
- 遍历所有子类,如果子类不包含该方法,则添加到子类中(若包含,相当于重写)
6. _createIndexWrapper(aClass, f)
对__index处理
local function _createIndexWrapper(aClass, f) if f == nil then return aClass.__instanceDict else return function(self, name) local value = aClass.__instanceDict[name] if value ~= nil then return value elseif type(f) == "function" then return (f(self, name)) else return f[name] end end endend
- f为空,则返回aClass.__instanceDict
- 如果__instanceDict包含name 则返回 <==> __index = __instanceDict
- 如果f为函数, __index = f(self,name)
- 否则,返回f[name]
7. _call(self, …)
调用new方法,使A:new() <==> A()
8. _tostring(self)
* 默认tostring方法*
9. middleclass.class(name, super)
创建一个类,并设置父类
* 如果super ~= nil 则调用subclass, 将那么添加到super的子类中
* 否则,创建一张默认表,并将DefaultMixin合并进去
实例解析
Metamethods
不需设置metatable的元方法,直接在当前类中定义,即可实现原方法。
以tostring为例:
Point = class('Point')function Point:initialize(x,y) self.x = x self.y = yendfunction Point:__tostring() return 'Point: [' .. tostring(self.x) .. ', ' .. tostring(self.y) .. ']'endp1 = Point(100, 200)p2 = Point(35, -10)print(p1)print(p2)Output:Point: [100, 200]Point: [35, -10]
- p1(实例)的__index为__instanceDict,所以调用tostring时,会去__instanceDict中去查找
- Pointer的__newindex为_declareInstanceMethod,在类中定义__tostring时,_declareInstanceMethod会将该方法加入到__instanceDict中
- 重写__tostring,相当于在自己的元表中定义该方法
- 其他元方法类似
Middleclass 4.x supports all the Lua metamethods. There are some restrictions:
* Overriding themetatable
metamethod is possible, but likely will give you trouble. Do this only if you know what you are doing.
* Metamethods not supported by the Lua version being used are not supported. For example, thelen
metamethod does not work in Lua 5.1 or LuaJIT without 5.2 compatibility.
mixins
类变量提供include方法,可以将一个table的域拷贝到另一个table中,被拷贝的table会触发included方法
- class.static表中提供include方法
- class的__index指向class.static
- 被合并的table 调用include方法
Private stuff
在类内定义局部变量,或者局部函数,外部不可访问
lua的作用于限制
其他
class = require("middleclass")A = class("A")A.n = 1B = A()print(B.n)B.n = 2print(B.n)print(A.n)Output:121
B是A的实例,B继承了n(B中没有n属性,则去__instanceDict中取)
当B对n赋值,则相当于在B表中添加属性,不会改变__instanceDict的值,再次获取该属性时,直接从B表中读,所以值为2,且不会改变A中的值
middleclass使用的表的简单总结
- __instanceDict 记录当前类,以及所有父类定义的实例方法(属性), __index指向自己
- __declaredMethods 记录当前类声明的方法(属性)
- subclasses 当前类的所有子类,弱引用
- static 静态表,定义new, include, isSubclassOf等方法,__index指向__instanceDict。
实例变量不能直接访问static表,必须通过.class.static访问。
类的静态方法可以通过class.static:func 来定义 - 类的默认表 定义__instanceDict,__declaredMethods, static等属性。
__index指向static表,可以直接使用static中的字段(A:new())。
__newIndex为_declareInstanceMethod方法,添加字段时会更新__instanceDict以及__declareMethods - 实例表 定义class属性,指向当前的类。 metatable为对应类的__instanceDict
- Lua middleclass(v4.1) 解析
- middleclass.lua分析
- lua middleclass 的一个要注意的问题,静态属性
- Lua解析1 TValue
- Glide V4源码解析
- middleclass源码阅读笔记
- android.support.v4.util.Pool 类解析
- android.support.v4.util.Pools源码解析
- android.support.v4.app.Fragment源码解析
- 网视秀 v4.1 bt
- v4
- lua 源代码解析
- Lua初学常见问题解析
- lua源代码解析
- Lua解析文件MD5
- cocos2dx lua json解析
- lua 解析url
- lua 源代码解析
- 修改外部css样式
- unicode 与 utf-8
- 常用五大算法详细介绍
- HDU-1992-Tiling a Grid With Dominoes-4列n行的骨牌-轮廓线DP
- SqlSugar 高性能ORM 2.4 性能超Dapper 5% 和原生一样
- Lua middleclass(v4.1) 解析
- android-下拉更多列表
- 172.The session of user SCOTT receives the following error after executing an UPDATE command on the
- 【Linux系统编程】进程间通信--共享内存
- 173.Which statement describes the effect on an index, when the indexed column for the rows is update
- 我的Android之旅(七)--Fragment及其生命周期
- android 广告页轮播
- 【工具】GDB常见调试命令
- iOS Swift 基础三