lua中“类”的实现
来源:互联网 发布:乳胶漆配色软件. 编辑:程序博客网 时间:2024/05/26 20:23
在之前的面试遇到考用lua实现类的题目。现在就补补这块知识点。
我们都知道Lua中的table是一个对象。拥有状态,拥有self,拥有独立于创建者和创建地的生命周期。
一个类就是一个创建对象的模具。Lua没有类的概念,但我们可以模拟类。
我们首先看看元表和元方法。这两个东西和我们模拟类有关。
Lua 本身是函数式的语言,但借助 metatable (元表)这个强大的工具,Lua 实现操作符重载易如反掌。就像两个表相加,只要我们在元表中写上__add方法就可以实现了。
meta={__add=function(op1,op2)op = {}op.x = op1.x + op2.xop.y = op1.y + op2.yreturn opend}a={x=1,y=1}setmetatable(a,meta)b={x=3,y=4}c = a + bprint(c.x, c.y) -- 输出 4,5 建立自己的类
通过这个方法,我们可以定义“类”的构造函数,析构函数。
除了与操作符重载有关的元方法以外,要建立自己的类,我们不得不认识另外一个元方法,它就是大名鼎鼎的“__index”。当表格搜寻成员未果的时候,Lua 会触发它,__index 所指向的元方法,元方法所返回的结果就成为了搜寻结果。如果没有这个元方法,那么访问结果为nil。__index元方法还可以直接为一张表(细数起来,这可是张表中表中表了)。
我们就用《Lua程序设计第二版》书中的例子说说Lua有关继承的典型示例吧。
假设要创建一些描述窗口的table,每个table中必须描述一些窗口参数,例如位置、大小及主题颜色等。所有这些参数都有默认值,因此希望在创建窗口对象时可以仅指定那些不同于默认值的参数。我们让新窗口从一个原型窗口处继承所有不存在的字段。首先,声明一个原型和一个构造函数,构造函数创建新的窗口,并使它们共享一个元表:
Window = {} --创建一个名字空间--使用默认值来创建一个原型Window.prototype = {x=0,y=0,width=100,height=100}Window.mt = {} --创建元表--声明构造函数function Window.new(o)setmetatable(o,Window.mt)return oend
现在,来定义__index元方法:
Window.mt.__index = function(table,key)return Window.prototype[key]end
在这段代码之后,创建一个新窗口,并查询一个它没有的字段:
w = Window.new{x=10,y=20}print(w.width) -->100
若Lua检测到w中没有某字段,但在其元表中却有一个__index字段,那么Lua就会以w(table)和"width"(不存在的key)来调用这个__index元方法。随后元方法用这个key来索引原型table,并返回结果。
在Lua中,将__index元方法用于继承是很普遍的方法,因此Lua还提供了一种更便捷的方式来实现此功能。__index元方法不必一定是一个函数,它还可以是一个table。当它是一个函数时,Lua以table和不存在的key作为参数来调用该函数,这就如同上述内容。而当它是一个table时,Lua就以相同的方式来重新访问这个table。因此,前例中__index的声明可以写为:
Window.mt.__index = Window.prototype我们现在可以写一个简历的类了:
A = {x=0,y=0}--这句是重定义元表的索引,必须要有,A.__index = A--模拟构造体,一般名称为new()function A:new(x,y) local self = {} setmetatable(self, A) --必须要有 self.x = x self.y = y return self endfunction A:test() print(self.x,self.y)endobjA = A:new(1,2)objA:test()print(objA.x,objA.y)
那这个类怎样被继承?
假设有一个基类A:
A = {}function A:new(o)o = o or {}setmetatable(o,self)self.__index = selfreturn oendfunction A:funName()print('A')end
若想从这个类派生出一个子类B,以使其能打印出类名。则先需要创建一个空的类,从基类继承所有的操作:
B = A:new()直到现在,B还只是A的一个实例。如下所示:
s = B:new()
B从A中继承了new,就像继承其他方法一样。不过这次new在执行时,它的self参数表示为B。因此,s的元表为B,B中字段__index的值也是B。s继承自B,而B又继承自A。当B重写funName()函数:
function B:funName()print('B')end
现在调用
s:funName()
输出的是B。
参考:
《Lua程序设计第二版》
Lua的类实现继承、多态以及setmetatable方法:http://blog.csdn.net/ym012/article/details/7206968
lua,让人惊叹的艺术:http://bbs.uc.cn/thread-2663965-1-1.html
lua面向对象是怎么实现的:http://www.2cto.com/kf/201402/280177.html(这个没有用到metatable ,相当来说易懂点)
云风oo:http://blog.codingnow.com/cloud/LuaOO
- lua学习:lua中“类”的实现
- lua学习:lua中“类”的实现
- lua学习:lua中“类”的实现
- lua学习:lua中“类”的实现
- Lua中类的实现
- lua中“类”的实现
- lua中“类”的实现
- lua中“类”的实现
- Lua 中实现类
- Lua中实现类的原理 值得一看
- Lua中实现类的原理
- Lua中实现类的原理
- Lua中实现类的原理
- lua中实现类的继承
- Lua中实现类的原理
- Lua中实现类的原理
- Lua中实现类的原理
- cocos2dx + lua 中实现 lua的MVC
- 俄罗斯轮盘(Russian Roulette)
- DSP、CAN、USB、以太网系统
- UVA 10167 Birthday Cake
- cocos生成keystore及其项目配置的一些BUG
- xcode语法高亮插件
- lua中“类”的实现
- 倾情大奉送--Spark入门实战系列
- 大数据的机遇与挑战:清华、复旦、中科院、春雨移动及考拉征信专家的观点
- Android4.0 Launcher拖拽原理分析
- C++中的单例模式
- 不同环境间FSG报表组件的传输
- SURF算法
- 在安卓开发中实现退出App时销毁所有Activity
- FPGA+DSP视频监控