Lua本身是没有面向对象支持的,但面向对象编程在逻辑复杂的大型工程却很有用。于是很多人用Lua本身的数据结构table来模拟面向对象。最简单的一种方法是把对象的方法、成员都放到table中。如:

-- file:test.lualocal test = {}function test:get_x()return self.x or 0
endfunction test:set_x( _x )self.x = _x
endlocal test_module = {}function test_module.new()local t = {}for k,v in pairs( test ) dot[k] = vendreturn t
endreturn test_module

调用也比较简单:

-- file:main.lualocal test = require "test"local _t = test.new()_t:set_x( 999 )
print( _t:get_x() )

这已经很像面向对象编程。但我们可以看到这样写有些缺点:

1.数据和方法混在一起(当然这不是什么大问题,C++也是这样)

2.每创建一个对象,都要将方法复制一遍

3.没法继承

Lua有强大的元表(metatable),利用它我们可以更优雅地封装一下:

1.先统一封装一个面向对象函数:

-- file:oo.lualocal oo = {}local cls = {}local function new( clz )local t = {}setmetatable(t, clz)return t
endfunction oo.class( parent,name )local t = {}cls[name] = tparent = parent or {}rawset( t,"__index",t )setmetatable( t,{ __index = parent,__call = new } )return t
endreturn oo

2.然后重新写类的实现:

-- file:test.lualocal oo = require "oo"local test = oo.class( nil,... )function test:get_x()return self.x or 0
endfunction test:set_x( _x )self.x = _x
endreturn test

3.调用也更加简单了:

-- file:main.lualocal Test = require "test"local _t = Test()_t:set_x( 999 )
print( _t:get_x() )

可以看到,利用元表,我们可以把方法全部放到元表中,与对象成员数据分开。元表本身是一个表,它也有元表,可以把父类作为元表的元表实现继承。我们如果再扩展一下,还可以实现对象方法的热更,对象统计...

  虽然元表很巧妙,但它的实现是有代价的。Lua得先在table中查找是否有相同的值,如果没有,再去元表找。如果是多重继承,那么还得一层层元表找下去。下面我们来测试一下元表的效率。

-- lua metatable performance test
-- 2016-04-01
-- xzclocal test = function( a,b ) return a+b endlocal empty_mt1 = {}
local empty_mt2 = {}
local empty_mt3 = {}
local empty_mt4 = {}
local empty_mt5 = {}
local empty_mt6 = {}
local empty_mt7 = {}
local empty_mt8 = {}local mt = {}
mt.test = testlocal mt_tb = {}setmetatable( empty_mt8,{__index = mt} )
setmetatable( empty_mt7,{__index = empty_mt8} )
setmetatable( empty_mt6,{__index = empty_mt7} )
setmetatable( empty_mt5,{__index = empty_mt6} )
setmetatable( empty_mt4,{__index = empty_mt5} )
setmetatable( empty_mt3,{__index = empty_mt4} )
setmetatable( empty_mt2,{__index = empty_mt3} )
setmetatable( empty_mt1,{__index = empty_mt2} )
setmetatable( mt_tb,{__index = empty_mt1} )local tb = {}
tb.test = testlocal ts = 10000000f_tm_start()
local cnt = 0
for i = 1,ts docnt = test( cnt,1 )
end
f_tm_stop( "call function native" )f_tm_start()
local cnt = 0
for i = 1,ts docnt = tb.test( cnt,1 )
end
f_tm_stop( "call function as table value" )f_tm_start()
for i = 1,ts docnt = empty_mt6.test( cnt,1 )
end
f_tm_stop( "call function with 3 level metatable" )f_tm_start()
for i = 1,ts docnt = mt_tb.test( cnt,1 )
end
f_tm_stop( "call function with 10 level metatable" )

在我的笔记本上测试,结果为:

local ts = 10000000
call function native    1091772 microsecond
call function as table value    1287172 microsecond
call function with 3 level metatable    2014431 microsecond
call function with 10 level metatable   3707181 microsecond

可以看到,采用第一种方法封闭的面向对象比原生函数调用慢不了多少,但用第二种方法实现3重继承的话,几乎慢了一倍。

  在实际项目中,我们用的是第二种封装方式,最主要是可以继承和热更代码。虽然效率有一定影响,但实际应用中逻辑消耗的时间比函数调用的时间仍大得多,这点损耗可以接受。这个世界上没有最快,只有更快,不必盯着程序的效率看。在满足项目要求的情况下,开发效率也是很值得考虑的。

转载于:https://www.cnblogs.com/coding-my-life/p/5352272.html

lua面向对象封装及元表(metatable)性能测试相关推荐

  1. Lua 元表(Metatable)

    在 Lua table 中我们可以访问对应的key来得到value值,但是却无法对两个 table 进行操作. 因此 Lua 提供了元表(Metatable),允许我们改变table的行为,每个行为关 ...

  2. lua学习笔记之元表和元方法

    元表允许当遇到未知操作时,改变值的行为.例如,使用元表,可以定义表a与表b的关系运算a+b.当lua尝试两个表相加时,会检查是否其中一个有元表并且元表是否有__add字段. 元表在面向对象的术语中是一 ...

  3. 雷林鹏分享:Lua 面向对象

    面向对象编程(Object Oriented Programming,OOP)是一种非常流行的计算机编程架构. 以下几种编程语言都支持面向对象编程: C++ Java Objective-C Smal ...

  4. Lua 面向对象 创建类实例

    Lua 面向对象 创建类实例 面向对象编程(Object Oriented Programming,OOP)是一种非常流行的计算机编程架构 常用的面向对象编程语言:C++.Java.Object-C. ...

  5. JS面向对象一:MVC的面向对象封装

    JS面向对象一:MVC的面向对象封装 MDNjavascript面向对象 面向对象(Object-Oriented) 面向对象里面向的意思是以...为主,面向对象编程既以对象为主的编程. 面向对象的一 ...

  6. 面向对象-封装、继承、多态

    面向对象-封装.继承.多态 面向对象-封装 一.封装: private 数据类型 _名字;   --成员变量 public 默认一致 名字 属性 {  get{ return _名字; }  set{ ...

  7. javascript对XMLHttpRequest异步请求的面向对象封装

    对XMLHttpRequest异步请求的面向对象封装,需要的朋友可以参考下 function CallBackObject() { this.XmlHttp = this.GetHttpObject( ...

  8. php面向对象分页,PHP基于面向对象封装的分页类示例

    本文实例讲述了php基于面向对象封装的分页类.分享给大家供大家参考,具体如下: class page { protected $num;//每页显示条数 protected $total;//总记录数 ...

  9. python封装举例_Python面向对象封装操作案例详解

    本文实例讲述了Python面向对象封装操作.分享给大家供大家参考,具体如下: 目标 封装 小明爱跑步 存放家具 01. 封装 封装 是面向对象编程的一大特点 面向对象编程的 第一步 -- 将 属性 和 ...

最新文章

  1. KMeans聚类并绘制聚类后的决策边界
  2. 拖拽的原生和jQuery写法
  3. 调整体态的最佳瑜珈调息法
  4. 网站优化之如何才能防止域名被恶意指向?
  5. C++学习19 类的多继承
  6. JavaScript代码(一)
  7. 面向对象和面向过程连接数据库
  8. 《统计学:从数据到结论》学习笔记(part3)--任何统计量,只要人们觉得合适就可以当成估计量
  9. 告别花瓶:2015年智能电视路在何方?
  10. 线程间的协作(2)——生产者与消费者模式
  11. 网页底部的版权信息_Shopify底部的版权信息(Powered by Shopify )如何删除
  12. 接口 EnvironmentAware
  13. flink streamGraph生成
  14. 刚刚,百度宣布王海峰升任 CTO
  15. Linux操作系统下/etc/hosts文件
  16. 视频能力如何应对5G时代的流量爆炸
  17. win10下乌龟git安装和使用
  18. unity3d插件分享paint in 3d插件的简单使用
  19. PR短视频特效转场 快速画面分割视频转场过渡PR转场模板
  20. 利用matlab导入数据+命令行 快速选取excel部分内容

热门文章

  1. python-深浅拷贝
  2. dijkstra堆优化(multiset实现-大大减小代码量)
  3. WPF——Expander控件(转)
  4. 从程序员到项目经理(9):程序员加油站 -- 再牛也要合群【转载】
  5. MaciOS之多线程(转)
  6. (转)2-sat 专题
  7. 一图胜千言,这本交互式线代教科书让你分分钟理解复杂概念,佐治亚理工出品...
  8. ICCV 2019 | 厦大提出快速NAS检索方法,四小时搜索NN结构
  9. 提高GAN训练稳定性的9大tricks
  10. Python项目实战:带领你爬取sexy的福利图片