在Lua中进行面向对象编程时有几种方法,上一小结介绍了一种使用__index元方法的做法。

下面要介绍另一种方法,可以在Lua中实现多继承.

  关键一点,在于用函数作为__index元字段。

  多重继承意味着一个类可以有多个基类。因此无法使用一个类中的方法来创建子类,而是需要定义一个特殊的函数来创建。

它的参数表示新类的所有基类。创建时它会设置元表中的__index元方法。而多重继承正是在这个__index元方法中完成的。

类和基类之间的关系不同于类和实例之间的关系。尤其是一个类不能同时作为其实例和子类的元表。

在下面的createClass例子中,将类作为其实例的元表,并创建了另一个table作为类的元表。

用之前的Account和新的一个类Named去实现createClass。

新的Named有两个方法,setname和getname

Named = {}
function Named:getname()
return self.name
end
function Named:setname(n)
self.name = n
end

创建新类的代码:

--在table plist中查找"k"
local function search(k , plist)
for i = , #plist do
local v = plist[i][k] --尝试第i个基类
if v then return v end
end
end function createClass(...)
local c = {} --新类
local parents = {...}
--类在其父类列表中的搜索方法
setmetatable(c ,{__index = function( t , k )
return search( k , parents)
end
}) --将'c'作为其实例的元表
c.__index = c --为这个新类定义一个新的构造函数
function c:new(o)
o = o or {}
setmetatable(o,c)
return o
end
return c --返回新类
end

假设要创建一个新类NameAccount,同时从Account和Named派生,那么只需要调用createClass:

NamedAccount = createClass(Account,Named)

如果要创建并使用实例:

account = NamedAccount:new{name  = "Paul"}    --创建实例
print(account:getname()) --> Paul --使用实例

首先Lua在account中找不到“getname”。就查找account中的元表__index字段。该字段为NamedAccount。它也没有“getname”。

所以Lua就找NamedAccount的__index,结果是一个函数。该函数先在Account中查找,再在Named中查找(找到就结束了)。

由于这项搜索具有复杂性,所以多重继承性能不如单一继承。

一个改进方法是将继承的方法复制到子类中:

setmetatable(c , {__index = function (t, k )
local v = search ( k , parents )
t[k] = v --保存下来,以备下次访问
return v
end})

一个缺点:当系统运行后就较难修改方法的定义,因为这些改变不会沿着继承向下传播。

以上内容来自:《Lua程序设计第二版》和《Programming in Lua  third edition 》

Chapter 16_3 多重继承的更多相关文章

  1. EFFECTIVE OBJECTIVE-C 2.0 TIPS 总结 CHAPTER 1 & CHAPTER 2

    下面只是对读到的所有 Tips 结合我平时开发中遇到的问题进行总结,每一个 Tips 和书中的每一条对应,本文的目的是去掉书中的大部分讨论的内容,让人能够马上使用这些 Tips,建议阅读过原书后食用更 ...

  2. J a v a 的“多重继承”

    接口只是比抽象类“更纯”的一种形式.它的用途并不止那些.由于接口根本没有具体的实施细节——也就是说,没有与存储空间与“接口”关联在一起——所以没有任何办法可以防止多个接口合并到一起.这一点是至关重要的 ...

  3. Modern C++ CHAPTER 2(读书笔记)

    CHAPTER 2 Recipe 2-1. Initializing Variables Recipe 2-2. Initializing Objects with Initializer Lists ...

  4. java提高篇(九)-----实现多重继承

    多重继承指的是一个类可以同时从多于一个的父类那里继承行为和特征,然而我们知道Java为了保证数据安全,它只允许单继承.有些时候我们会认为如果系统中需要使用多重继承往往都是糟糕的设计,这个时候我们往往需 ...

  5. 不可或缺 Windows Native (22) - C++: 多重继承, 虚基类

    [源码下载] 不可或缺 Windows Native (22) - C++: 多重继承, 虚基类 作者:webabcd 介绍不可或缺 Windows Native 之 C++ 多重继承 虚基类 示例1 ...

  6. scala 学习笔记(06) OOP(下)多重继承 及 AOP

    一.多继承 上篇trait中,已经看到了其用法十分灵活,可以借此实现类似"多重继承"的效果,语法格式为: class/trait A extends B with C with D ...

  7. Effective C++ -----条款40:明智而审慎地使用多重继承

    多重继承比单一继承复杂.它可能导致新的歧义性,以及对virtual继承的需要. virtual继承会增加大小.速度.初始化(及赋值)复杂度等等成本.如果virtual base classes不带任何 ...

  8. python基础——多重继承

    python基础——多重继承 继承是面向对象编程的一个重要的方式,因为通过继承,子类就可以扩展父类的功能. 回忆一下Animal类层次的设计,假设我们要实现以下4种动物: Dog - 狗狗: Bat ...

  9. Android Programming: Pushing the Limits -- Chapter 7:Android IPC -- ApiWrapper

    前面两片文章讲解了通过AIDL和Messenger两种方式实现Android IPC.而本文所讲的并不是第三种IPC方式,而是对前面两种方式进行封装,这样我们就不用直接把Aidl文件,java文件拷贝 ...

随机推荐

  1. Ubuntu环境openresty的安装

    Ubuntu环境openresty的安装 相关库的安装 安装openresty需要的库  apt-get install libreadline-dev libncurses5-dev libpcre ...

  2. Vim编辑器与Shell命令脚本

    章节简述: 本章节将教给您如何使用Vim编辑器来编写文档.配置主机名称.网卡参数以及yum仓库 ,熟练使用各个模式和命令快捷键. 我们可以通过Vim编辑器将Linux命令放入合适的逻辑测试语句(if. ...

  3. Linux 操作命令列表记录

    Linux 操作命令列表记录 SSH登录 登录 ## 范式 ssh [username]@[host] ## 例 ssh -p 1222 root@10.0.0.1 使用非默认端口(ssh默认端口22 ...

  4. 工厂模式Assembly.Load(path).CreateInstance 反射出错解决办法

    项目结构: DALFactory 反射代码反射 //使用缓存 private static object CreateObject(string AssemblyPath,string classNa ...

  5. jsp日期插件My97DatePicker 强大的日期控件 使用方便简单

    本文属转载(希望对编程爱好者有所帮助)详情请访问官方网站 http://www.my97.net/dp/index.asp 一. 简介 1. 简介 目前的版本是:4.7 2. 注意事项 My97Dat ...

  6. Tiny6410之按键裸机驱动

    操作步骤: 第一步:查看开发板电路原理图 找到LED 和按键的管脚所对应的寄存器 LED:(见Tiny6410之LED裸机驱动) nLED_1 - GPK4 nLED_2 - GPK5 nLED_3 ...

  7. Java中eclipse中添加源码依赖

    Window ->Preferences ->Java->instanlled jres  ->editrt.jarsource attachment一般在jdk的目录下的sr ...

  8. java中|与||有什么区别?那么&与&&呢

    ||当左边为真时,就不运行右边的表达式了|当左边为真,还是会运算右边的表达式&&当左边为假时,就不会运算右边的表达式&当左边为假时,还是会运算右边的表达式

  9. 【Python之路】第七篇--Python基础之面向对象及相关

    面向对象基础 基础内容介绍详见一下两篇博文: 面向对象初级篇 面向对象进阶篇 其他相关 一.isinstance(obj, cls) 检查obj是否是类 cls 的对象 class Foo(objec ...

  10. 在eclipse中生成实体类

    1.在eclipse的windows中选中preferences在查询框中输入driver definition 2.点击add在Name/type中选中mysql jdbc driver 5.1然后 ...