在之前的面试遇到考用lua实现类的题目。现在就补补这块知识点。

我们都知道Lua中的table是一个对象。拥有状态,拥有self,拥有独立于创建者和创建地的生命周期。

一个类就是一个创建对象的模具。Lua没有类的概念,但我们可以模拟类。

我们首先看看元表和元方法。这两个东西和我们模拟类有关。

Lua 本身是函数式的语言,但借助 metatable (元表)这个强大的工具,Lua 实现操作符重载易如反掌。就像两个表相加,只要我们在元表中写上__add方法就可以实现了。

  1. meta={
  2. __add=function(op1,op2)
  3. op = {}
  4. op.x = op1.x + op2.x
  5. op.y = op1.y + op2.y
  6. return op
  7. end
  8. }
  9. a={x=1,y=1}
  10. setmetatable(a,meta)
  11. b={x=3,y=4}
  12. c = a + b
  13. print(c.x, c.y) -- 输出 4,5 建立自己的类

通过这个方法,我们可以定义“类”的构造函数,析构函数。

除了与操作符重载有关的元方法以外,要建立自己的类,我们不得不认识另外一个元方法,它就是大名鼎鼎的“__index”。当表格搜寻成员未果的时候,Lua 会触发它,__index 所指向的元方法,元方法所返回的结果就成为了搜寻结果。如果没有这个元方法,那么访问结果为nil。__index元方法还可以直接为一张表(细数起来,这可是张表中表中表了)。

我们就用《Lua程序设计第二版》书中的例子说说Lua有关继承的典型示例吧。

假设要创建一些描述窗口的table,每个table中必须描述一些窗口参数,例如位置、大小及主题颜色等。所有这些参数都有默认值,因此希望在创建窗口对象时可以仅指定那些不同于默认值的参数。我们让新窗口从一个原型窗口处继承所有不存在的字段。首先,声明一个原型和一个构造函数,构造函数创建新的窗口,并使它们共享一个元表:

  1. Window = {} --创建一个名字空间
  2. --使用默认值来创建一个原型
  3. Window.prototype = {x=0,y=0,width=100,height=100}
  4. Window.mt = {} --创建元表
  5. --声明构造函数
  6. function Window.new(o)
  7. setmetatable(o,Window.mt)
  8. return o
  9. end

现在,来定义__index元方法:

  1. Window.mt.__index = function(table,key)
  2. return Window.prototype[key]
  3. end

在这段代码之后,创建一个新窗口,并查询一个它没有的字段:

  1. w = Window.new{x=10,y=20}
  2. 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的声明可以写为:

  1. Window.mt.__index = Window.prototype

我们现在可以写一个简历的类了:

  1. A = {x=0,y=0}
  2. --这句是重定义元表的索引,必须要有,
  3. A.__index = A
  4. --模拟构造体,一般名称为new()
  5. function A:new(x,y)
  6. local self = {}
  7. setmetatable(self, A)   --必须要有
  8. self.x = x
  9. self.y = y
  10. return self
  11. end
  12. function A:test()
  13. print(self.x,self.y)
  14. end
  15. objA = A:new(1,2)
  16. objA:test()
  17. print(objA.x,objA.y)

那这个类怎样被继承?

假设有一个基类A:

  1. A = {}
  2. function A:new(o)
  3. o = o or {}
  4. setmetatable(o,self)
  5. self.__index = self
  6. return o
  7. end
  8. function A:funName()
  9. print('A')
  10. end

若想从这个类派生出一个子类B,以使其能打印出类名。则先需要创建一个空的类,从基类继承所有的操作:

  1. B = A:new()

直到现在,B还只是A的一个实例。如下所示:

  1. s = B:new()

B从A中继承了new,就像继承其他方法一样。不过这次new在执行时,它的self参数表示为B。因此,s的元表为B,B中字段__index的值也是B。s继承自B,而B又继承自A。当B重写funName()函数:

  1. function B:funName()
  2. print('B')
  3. end

现在调用

  1. s:funName()

输出的是B。

lua学习:lua中“类”的实现的更多相关文章

  1. Lua学习----Lua基础数据类型

    前言 Lua有6中数据类型,分别是nil(空).boolean(布尔).number(数字).string(字符).table(表).function(函数) 在Lua中可以使用type函数来返回一个 ...

  2. Lua学习---Lua的控制结构

    前言 由于之前有c/c++.javascript基础,所以学Lua的时候喜欢拿来和前面的语言比较,这里主要和C比较 1.if...else Lua的if语句格式: if 条件 then 条件成立,运行 ...

  3. Lua学习----Lua的表达式

    前言 Lua的运算符和其他语言基本类似.但也有一点点区别 1.算术运算符 Lua的算术运算符加入了指数运算符^ print(2 ^ 10) -->打印 1024. 求2的10次方 2.关系运算符 ...

  4. Lua学习笔记一

    学习了有一周多了.之前一直不想献丑,但还是记录下这个过程. 第1章  开发软件搭建 1. ubuntu 下lua安装 sudo apt-get install lua5.1 2.win下的环境搭建. ...

  5. Lua学习笔记(一)-----C#和lua的交互

    一直以来对Lua热更新技术很感兴趣,在上周开始了对Lua的学习,主要学的是uLua. 直接上干货 准备工作: LuaInterface包括两个核心库一个是LuaInterface.dll,一个是Lua ...

  6. cocos进阶教程(1)Lua调用自定义C++类和函数的最佳实践

    第一层:纯C环境下,把C函数注册进Lua环境 a.lua 文件 )) a.c 文件 #include <lua.h> #include <lualib.h> #include ...

  7. lua学习笔记

    工作需要,上周对lua赶进度似地学习了一遍,主要参考<lua中文教程>一书,中间参考一些<lua游戏开发实践>,首先说说这两本书,后者不适合初学,里面是对一个游戏脚本系统进行粗 ...

  8. Cocos2d-x下Lua调用自定义C++类和函数的最佳实践[转]

    Cocos2d-x下Lua调用C++这事之所以看起来这么复杂.网上所有的文档都没讲清楚,是因为存在5个层面的知识点: 1.在纯C环境下,把C函数注册进Lua环境,理解Lua和C之间可以互相调用的本质 ...

  9. 【转】Cocos2d-x下Lua调用自定义C++类和函数的最佳实践

    转自:http://segmentfault.com/blog/hongliang/1190000000631630 关于cocos2d-x下Lua调用C++的文档看了不少,但没有一篇真正把这事给讲明 ...

  10. Lua学习笔记6:C++和Lua的相互调用

        曾经一直用C++写代码.话说近期刚换工作.项目组中的是cocos2dx-lua,各种被虐的非常慘啊有木有.     新建cocos2dx-lua项目.打开class能够发现,事实上就是C++项 ...

随机推荐

  1. Median of Two Sorted Arrays——算法课上经典的二分和分治算法

    There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two ...

  2. go中操作json

    package main import ( "encoding/json" "fmt" ) type Server struct { ServerName st ...

  3. Python 的十个自然语言处理工具

    原文 先mark,后续尝试. 1.NLTK NLTK 在用 Python 处理自然语言的工具中处于领先的地位.它提供了 WordNet 这种方便处理词汇资源的借口,还有分类.分词.除茎.标注.语法分析 ...

  4. C# HTML 生成 PDF

    原文出处:http://www.cnblogs.com/shanyou/archive/2012/09/07/2676026.html

  5. 【51nod】1594 Gcd and Phi

    题解 跟随小迪学姐的步伐,学习一下数论 小迪学姐太巨了! 这道题的式子很好推嘛 \(\sum_{i = 1}^{n} \sum_{j = 1}^{n} \sum_{d|\phi(i),\phi(j)} ...

  6. 简易解析ajax,javascript-XMLHttpRequest

    XMLHttpRequest可以提供不重新加载页面的情况下更新网页 <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/ ...

  7. React Native踩坑之无法启动Debug

    问题 在chrome启动debug模式,连接不到地址 解决办法 在模拟器中,ctrl+m调出command,选择dev setting,然后设置debug地址为localhost:8081

  8. 大数据开篇 MapReduce初步

    最近在学习大数据相关的东西,开这篇专题来记录一下学习过程.今天主要记录一下MapReduce执行流程解析 引子(我们需要解决一个简单的单词计数(WordCount)问题) 1000个单词 嘿嘿,100 ...

  9. margin padding 图

  10. 【BZOJ 2007】 2007: [Noi2010]海拔 (平面图转对偶图+spfa)

    2007: [Noi2010]海拔 Time Limit: 20 Sec  Memory Limit: 552 MBSubmit: 2504  Solved: 1195 Description YT市 ...