基类:基类定义了所有对于派生类来说普通的属性和方法,派生类从基类继承所需的属性和方法,且在派生类中增加新的属性和方法。

继承:继承是C++语言的一种重要机制,它允许在已定义的类的基础上产生新类。

lua基类和C++基类极为相似,但是lua中却没有继承这一说,更没有所谓的派生类。lua只能通过一种行为(元表)来模拟C++继承这一方法。

元表:lua中提供的元表是用于帮助lua数据变量完成某些非预定义功能的个性化行为,当它做某一种操作,然而self表中却没有定义实现这种操作的方法,那么为了实现这一操作便会去元表中找实现这一操作的方法。

如果每一层的元表都定义一种方法指向上一层要“继承”的lua表,这样是不是就和C++继承一样了,有木有!

元方法:C++中的继承不会改变语言的常规行为。但是lua中却提供了一种可以改变table行为的方法,有两种可以改变的table行为:(__index元方法)查询table及( __newindex元方法)修改table中不存在的字段

(1)__index元方法:当对元表中不存在的字段进行访问时,得到的结果为nil。通过定义这个元表的__index,那个访问结果将由这个方法决定。

这个方法也是“继承”父类的方法。

(2)__newindex元方法:当对元表中不存在的字段进行赋值时,解释器会先找到这个元表的__newindex,如果有就调用它,对__newindex指向的表进行赋值操作, 如果没有才对self表进行赋值。

 --保存类类型的虚表
local _class = {} GLOBAL_OBJ_COUNT = {}
ENABLE_OBJ_COUNT = function FindClassName(target, depth)
for key,value in pairs(_G) do
if value == target then
return key
end
end
end function ClasCountRetain(c)
local key = FindClassName(c)
if GLOBAL_OBJ_COUNT[key] == nil then
GLOBAL_OBJ_COUNT[key] =
else
GLOBAL_OBJ_COUNT[key] = GLOBAL_OBJ_COUNT[key] +
end
end function ClasCountRelease(c)
local key = FindClassName(c)
if GLOBAL_OBJ_COUNT[key] == nil then
GLOBAL_OBJ_COUNT[key] = ---标识异常
else
GLOBAL_OBJ_COUNT[key] = GLOBAL_OBJ_COUNT[key] -
end
end function PrintLuaClassCount( ... )
print("PrintLuaClassCount.............")
for key,value in pairs(GLOBAL_OBJ_COUNT) do
print("PrintLuaClassCount:"..key..":",value)
end
end function BaseClass(super) -- 生成一个类类型
local class_type = {}
-- 在创建对象的时候自动调用
class_type.__init = false
class_type.__delete = false
class_type.super = super class_type.New = function(...) --定义New成员方法
-- 生成一个类对象
local obj = {}
obj._class_type = class_type -- 在初始化之前注册基类方法
setmetatable(obj, { __index = _class[class_type] }) -- 调用初始化方法
do
local create
create = function(c, ...)
if c.super then
create(c.super, ...) --对所有基类都进行init
end
if ENABLE_OBJ_COUNT ~= then
ClasCountRetain(c)
end
if c.__init then
c.__init(obj, ...)
end
end create(class_type, ...)
end -- 注册一个delete方法
obj.DeleteMe = function(self)
local now_super = self._class_type
while now_super ~= nil do
if ENABLE_OBJ_COUNT ~= then
ClasCountRelease(now_super)
end
if now_super.__delete then
now_super.__delete(self) --对所有基类都进行delete
end
now_super = now_super.super
end
end return obj
end local vtbl = {}
_class[class_type] = vtbl setmetatable(class_type, {__newindex =
function(t,k,v)
vtbl[k] = v --赋值操作时self找不到的字段则对vtbl表赋值
end
,
__index = vtbl, --For call parent method
}) if super then
setmetatable(vtbl, {__index = --元表做“继承”操作
function(t,k)
local ret = _class[super][k]
return ret
end
})
end return class_type
end

lua中基类和“继承机制”的更多相关文章

  1. C++中基类虚析构函数的作用及其原理分析

    虚析构函数的理论前提是 执行完子类的析构函数,那么父类的虚构函数必然会被执行. 那么当用delete释放一个父类指针所实例化的子类对象时,如果没有定义虚析构函数,那么将只会调用父类的析构函数,而不会调 ...

  2. C/C++ 多继承{虚基类,虚继承,构造顺序,析构顺序}

    C/C++:一个基类继承和多个基类继承的区别 1.对多个基类继承会出现类之间嵌套时出现的同名问题,如果同名变量或者函数出现不在同一层次,则底层派生隐藏外层比如继承基类的同名变量和函数,不会出现二义性, ...

  3. Python的程序结构[2] -> 类/Class[1] -> 基类与继承

    基类与继承 / Base Class and Inheritance Class 面向对象的特性使得 Python 中不可避免地需要使用到类和类的继承,类的继承可以使得代码很好的被重用.下面以一些代码 ...

  4. 详解C++中基类与派生类的转换以及虚基类

    很详细!转载链接 C++基类与派生类的转换在公用继承.私有继承和保护继承中,只有公用继承能较好地保留基类的特征,它保留了除构造函数和析构函数以外的基类所有成员,基类的公用或保护成员的访问权限在派生类中 ...

  5. C++中基类的析构函数为什么要用virtual虚析构函数

    知识背景 要弄明白这个问题,首先要了解下C++中的动态绑定. 关于动态绑定的讲解,请参阅:  C++中的动态类型与动态绑定.虚函数.多态实现 正题 直接的讲,C++中基类采用virtual虚析构函数是 ...

  6. 【转载】Lua中实现类的原理

    原文地址 http://wuzhiwei.net/lua_make_class/ 不错,将metatable讲的很透彻,我终于懂了. --------------------------------- ...

  7. 关于Python中的类普通继承与super函数继承

    关于Python中的类普通继承与super函数继承 1.super只能用于新式类 2.多重继承super可以保公共父类仅被执行一次 一.首先看下普通继承的写法 二.再看看super继承的写法 参考链接 ...

  8. c#中判断类是否继承于泛型基类

    在c#中,有时候我们会编写类似这样的代码: public class a<T> { //具体类的实现 } public class b : a<string>{} 如果b继承a ...

  9. 关于Java中基类构造器的调用问题

    在<Java编程思想>第7章复用类中有这样一段话,值得深思.当子类继承了父类时,就涉及到了基类和导出类(子类)这两个类.从外部来看,导出类就像是一个与基类具有相同接口的新类,或许还会有一些 ...

随机推荐

  1. Yii 1开发日记 -- Ajax实现点击加载下一页

    功能实现:先输出一页的内容,然后点击加载下一页,如图 1.控制器中 /** * 消费记录:列出用户购买章节的记录 */ public function actionMyPayHis() { //点击加 ...

  2. url带#号,微信授权,微信分享那些坑

    微信授权的方法是,在项目里面配置拦截器(此处可以参考各个框架的拦截器)没有拦截器也可以,反正意思就是跳转到项目里的时候判断微信环境 如果是微信环境, 判断微信环境的方法是 var ua = windo ...

  3. shell脚本比较两个数大小

    #/bin/bash read -p "请输入第一个数:" a read -p "请输入第二个数:" b if [ $a -gt $b ] #判断第一个数是不是 ...

  4. BFS_Maze_求解迷宫最短路径

    /* 10 10 #.######.# ......#..# .#.##.##.# .#........ ##.##.#### ....#....# .#######.# ....#..... .## ...

  5. javase-->基础知识(二)

    1.算术运算符 7种:+,-,*,/,%,++,--;          --------------------注意不要想当然,按照类型规则来计算 ++在变量前,先加1再取变量使用 --同理 在变量 ...

  6. 【转】Android 底层开发的几点

    我干了3年Android sdk开发,觉得到了瓶劲没法更进一步,于是花了一年多点时间,大概摸到点门径.根据前辈的经验,Android底层完全入门需要两年. 先说下我的入门过程:第零步,下载源码,我下的 ...

  7. android shape的使用(转)

    shape用于设定形状,可以在selector,layout等里面使用,有6个子标签,各属性如下: <?xml version="1.0" encoding="ut ...

  8. zeromq系列

    ZeroMQ系列 之NetMQ 一:zeromq简介 二:NetMQ 请求响应模式 Request-Reply 三:NetMQ 发布订阅模式 Publisher-Subscriber 四:NetMQ ...

  9. angular之上滑换页指令

    healthmallDirectives.directive("goodsTopRefresh", ['$window',function ($window) { return { ...

  10. git 查看某文件的修改历史

    前提 先进入此文件所在的目录下 1. git log filename可以看到fileName相关的commit记录2. git log -p filename可以显示每次提交的diff3. 只看某次 ...