【quick-cocos2d-x】Lua 面向对象(OOP)编程与元表元方法
版权声明:本文为博主原创文章,转载请注明出处。
面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物。
早期的计算机编程是基于面向过程的方法,通过设计一个算法就可以解决当时的问题。随着计算机技术的不断提高,计算机被用于解决越来越复杂的问题。面向过程式的编程思想很难良好的解决这些复杂的问题,通过面向对象的方法,更利于用人理解的方式对复杂系统进行分析、设计与编程。同时,面向对象能有效提高编程的效率,通过封装技术,消息机制可以像搭积木的一样快速开发出一个全新的系统。
但是随着软件行业的飞速发展,渐渐的有人开始觉得面向对象编程让代码显的非常复杂,工程庞大。开始有一部分人回归到了面向过程编程,开始运用面向对象和面向过程结合的方式进行开发。
面向对象最主要的两个概念就是对象和类,能够充分理解这两个概念的人自然也很容易理解面向对象的编程思想。
所谓对象,就是用来描述客观存在的一个实体,它是构成系统的一个基本单位。一个对象应该由若干属性组成,这些属性用于描述这个实体的信息,比如某个人的名字。另外还应该包含一些方法,用于描述实体的动作,比如某个人吃饭的过程。
类是具有相同属性和方法的所有对象实体的抽象,类的内部为这些对象提供了统一的抽象描述。比如所有人都有名字,那么“人”这个类就应该包含一个属性叫做人名。所有的人都有这个属性,类的方法也是一样的道理。
Lua语言中没有类的定义,也不能定义类,但是我们可以使用table来模仿对象,如下:
- -- 定义一个表来模拟对象,将id和name看成的它的属性
- local person = {id = , name = "yzn",}
- -- 给对象添加方法
- function person.sayHello(self)
- print("你好,我的名字是" .. self.name)
- end
- - - 访问属性
- print(person.id)
- - - 调用方法
- person:sayHello()
接下来我们来访问person的属性和调用sayHello方法。发现无论是语法还是效果上面都和Java等其它语言操作对象的方式极其类似。但是值得注意的是我在调用方法的时候person后面用的是冒号(:)来调用sayHello方法,而不是使用一点。这其实是Lua的一个语法糖衣,使用冒号调用的时候Lua会自动将调用者当成函数的第一个参数的实参传递到函数内部去。所以我就没有传递参数给sayHello的self参数那边。
也是就是:
- person:sayHello()
与
- person.sayHello(person)
是一样的效果,冒号和点号只是用来决定是否需要手动传递第一个参数而已。
现在我们来看下类是如何模拟出来的:
- -- 定义一个Person表,当成类。添加一个属性id,和一个方法toString
- Person = {
- id = "",
- toString = function(p)
- print("id = ", p.id)
- end
- }
- -- 给Person再添加一个new函数,用于实例化对象。
- function Person.new()
- -- 定义一个表,当成被实例化出来的对象
- obj = {}
- -- 设置表的元表
- setmetatable(obj, Person)
- -- 设置__index方法为自身
- Person.__index = Person
- -- 返回创建的实例对象
- return obj
- end
- -- 调用new函数实例化对象
- local obj = Person.new()
- -- 访问属性
- print("obj.id = ", obj.id)
- -- 调用方法
- obj:toString()
其实Lua中就是通过设置元表的方式来实现继承关系的,这里所谓的类和对象,其实就是让一个obj表继承Person这个表(设置obj的元表为Person)。然后设置元方法__index为Person,这样我们访问obj的id属性时,它在自己的表中没有找到就会调用元方法__index去元表里面找,也就是去Person里面去找,然后返回了Person的id属性的值,方法调用也是一样的。如果没有设置__index,那么没有找到会直接返回nil。
元表和元方法,是Lua内置的一些操作。Lua的每个变量都具有一张元表,我们可以通过getmetatable(var)函数得到对象的元表。而对于setmetatable()方法,设置元表只能针对于table类型的变量。要修改设置其他值的元表,我们需要通过C的API来实现。
table默认是没有设置其元表的,我们可以通过以下代码进行验证:
- local tab1 = {, , }
- print(getmetatable(tab1)) -- 输出nil
其实所谓的元表就是一个普通的表,我们现在来设置下tab1的元表:
- local tab1 = {, , }
- -- 定义一个普通的空表作为元表
- local mt = {}
- setmetatable(tab1, mt)
- print(getmetatable(tab1)) -- 输出table
我们甚至可以给上面的mt添加一个项,然后获取出tab1的元表进行dump查看是否就是mt:
- local tab1 = {, , }
- -- 定义一个普通的空表作为元表
- local mt = { id = , }
- setmetatable(tab1, mt)
- dump(getmetatable(tab1)) -- 输出表里面的所有内容
我在quick-player模拟器上面运行,控制台窗口输入的内容如下图所示。
我们可以清晰的看到确实是设置元表成功了。
接下来我们来重载Lua的运算符。Lua的运算符是通过元方法进行计算的,元方法分为算数元方法和关系元方法。Lua的元方法都是以双下划线开头的,比如上面提到的__index等。
所谓的算数元方法就是在进行算数运算的时候会被调用的方法。比如进行加法的__add和减法的__sub。我们这里以加法运算符为例,在进行重载加法运算符(+)之前,对两个table进行相加肯定活报错。所以,我们现在先对加法进行重载,代码如下:
- local tab1 = {"a", "b", "c"}
- -- 定义一个普通的空表作为元表
- local mt = {}
- -- 设置tab1的元表为mt
- setmetatable(tab1, mt)
- -- 重写元方法
- mt.__add = function(t1, t2)
- local t = {}
- for i, v in ipairs(t1) do
- table.insert(t, v)
- end
- for i, v in ipairs(t2) do
- table.insert(t, v)
- end
- return t
- end
- -- 定义另一个table
- local tab2 = {"d", "e",}
- -- 对tab进行加法运算,会触发__add元方法
- local tab3 = tab1 + tab2
- -- 打印计算后的结果
- dump(tab3)
运行后看到打印的tab3的值如下所示:
可见我们重载是成功了,其他的元方法重载和加法的基本一致。
【quick-cocos2d-x】Lua 面向对象(OOP)编程与元表元方法的更多相关文章
- PHP面向对象(OOP)编程入门教程
面向对象编程(OOP)是我们编程的一项基本技能,PHP5对OOP提供了良好的支持.如何使用OOP的思想来进行PHP的高级编程,对于提高 PHP编程能力和规划好Web开发构架都是非常有意义的.下面我们就 ...
- 【PHP面向对象(OOP)编程入门教程】1.什么是面向对象?
面向对象编程(Object Oriented Programming, OOP, 面向对象程序设计)是一种计算机编程架构,OOP的一条基本原则是计算机程序是由单个能够起到子程序作用的单元或对象组合而成 ...
- php面向对象(OOP)编程完全教程
摘自:http://www.php-note.com/article/detail/41 面向对象编程(OOP)是我们编程的一项基本技能,PHP5对OOP提供了良好的支持.如何使用OOP的思想来进行P ...
- PHP面向对象(OOP)编程入门教程链接
PHP官方学习OOP: http://php.net/manual/zh/oop5.intro.php 从其他博主学习:(以下链接来源: http://blog.snsgou.com/post-41. ...
- 【PHP面向对象(OOP)编程入门教程】2.什么是类,什么是对象,类和对象这间的关系
类的概念:类是具有相同属性和服务的一组对象的集合.它为属于该类的所有对象提供了统一的抽象描述,其内部包括属性和服务两个主要部分.在面向对象的编程语言中,类是一个独立的程序单位,它应该有一个类名并包括属 ...
- lua中 table 重构index/pairs元方法优化table内存占用
转载请标明出处http://www.cnblogs.com/zblade/ lua作为游戏的热更新首选的脚本,其优势不再过多的赘述.今天,我主要写一下如何重写lua中的元方法,通过自己的重写来实现对l ...
- PHP面向对象(OOP)编程入门教程————如何实例化对象?
我们上面说过面向对象程序的单位就是对象,但对象又是通过类的实例化出来的,既然我们类会声明了,下一步就是实例化对象了. 当定义好类后,我们使用new关键字来生成一个对象. $对象名称 = new 类名称 ...
- js面向对象oop编程
理解对象 对象这个词如雷贯耳,同样出名的一句话:XXX语言中一切皆为对象! 对象究竟是什么?什么叫面向对象编程? 对象(object),台湾译作物件,是面向对象(Object Oriented)中的术 ...
- 【PHP面向对象(OOP)编程入门教程】23.自动加载类 __autoload()函数
很多开发者写面向对象的应用程序时,对每个类的定义建立一个 PHP 源文件.一个很大的烦恼是不得不在每个脚本(每个类一个文件)开头写一个长长的包含文件的列表. 在软件开发的系统中,不可能把所有的类都写在 ...
随机推荐
- Android开发常用代码片段
拨打电话 public static void call(Context context, String phoneNumber) { context.startActivity( new Inten ...
- 用rbenv给整个系统安装ruby(所有用户都可用)
rbenv非常好用,但有一个小问题,每个用户都需要单独安装和设置版本. 下面安装步骤可以安装在/usr/local/rbenv下,所有用户都可以共享rbenv. #rbenv安装(/usr/loc ...
- 如何通过图片在 HTTPS 网站中获取 HTTP 接口数据
<script> (function() { var Decode=function(b){var e;e=[];var a=b.width,c=b.height,d=document.c ...
- nginx添加nginx_mod_h264_streaming-2.2.7模块编译报错
报错ngx_http_streaming_module.c:158: 错误:‘ngx_http_request_t’ 没有名为 ‘zero_in_uri’ 的成员.这需要修改nginx_mod_h26 ...
- cocos2d-x 开启深度测试验 实现 遮挡
CCDirector::sharedDirector()->setDepthTest(true); spr->setVertexZ(xxx);
- Miller_Rabin (米勒-拉宾) 素性测试
之前一直对于这个神奇的素性判定方法感到痴迷而又没有时间去了解.借着学习<信息安全数学基础>将素性这一判定方法学习一遍. 首先证明一下费马小定理. 若p为素数,且gcd(a, p)=1, 则 ...
- 【笨嘴拙舌WINDOWS】BMP图片浏览器
要将文件显示成图片这其中需要经过 1.将磁盘文件内容读取到内存: 2.将文件对应内存里包含的像素为以及像素信息转化为显示驱动器能理解的格式: 3.将转化过后的内存送到显卡的缓存区 4.显示器读取缓存现 ...
- UVa 537 Artificial Intelligence?
题目大意:输入一个字符串,根据物理公式P=U*I,已知其中两个量,求第三个量,结果保留两位小数. Artificial Intelligence? Physics teachers in hig ...
- ubuntu 11.04 源 更新不了,全显示ign、404
原文地址:http://blog.csdn.net/enjio/article/details/11603373 ubuntu 11.04 源 更新不了 分类: 开发相关2013-09-12 14 ...
- App开放接口api安全性—Token签名sign的设计与实现
前言 在app开放接口api的设计中,避免不了的就是安全性问题,因为大多数接口涉及到用户的个人信息以及一些敏感的数据,所以对这些接口需要进行身份的认证,那么这就需要用户提供一些信息,比如用户名密码等, ...