版权声明:本文为博主原创文章,转载请注明出处。

  面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物。 
早期的计算机编程是基于面向过程的方法,通过设计一个算法就可以解决当时的问题。随着计算机技术的不断提高,计算机被用于解决越来越复杂的问题。面向过程式的编程思想很难良好的解决这些复杂的问题,通过面向对象的方法,更利于用人理解的方式对复杂系统进行分析、设计与编程。同时,面向对象能有效提高编程的效率,通过封装技术,消息机制可以像搭积木的一样快速开发出一个全新的系统。 
  但是随着软件行业的飞速发展,渐渐的有人开始觉得面向对象编程让代码显的非常复杂,工程庞大。开始有一部分人回归到了面向过程编程,开始运用面向对象和面向过程结合的方式进行开发。 
  面向对象最主要的两个概念就是对象和类,能够充分理解这两个概念的人自然也很容易理解面向对象的编程思想。 
  所谓对象,就是用来描述客观存在的一个实体,它是构成系统的一个基本单位。一个对象应该由若干属性组成,这些属性用于描述这个实体的信息,比如某个人的名字。另外还应该包含一些方法,用于描述实体的动作,比如某个人吃饭的过程。 
  类是具有相同属性和方法的所有对象实体的抽象,类的内部为这些对象提供了统一的抽象描述。比如所有人都有名字,那么“人”这个类就应该包含一个属性叫做人名。所有的人都有这个属性,类的方法也是一样的道理。 
  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)编程与元表元方法的更多相关文章

  1. PHP面向对象(OOP)编程入门教程

    面向对象编程(OOP)是我们编程的一项基本技能,PHP5对OOP提供了良好的支持.如何使用OOP的思想来进行PHP的高级编程,对于提高 PHP编程能力和规划好Web开发构架都是非常有意义的.下面我们就 ...

  2. 【PHP面向对象(OOP)编程入门教程】1.什么是面向对象?

    面向对象编程(Object Oriented Programming, OOP, 面向对象程序设计)是一种计算机编程架构,OOP的一条基本原则是计算机程序是由单个能够起到子程序作用的单元或对象组合而成 ...

  3. php面向对象(OOP)编程完全教程

    摘自:http://www.php-note.com/article/detail/41 面向对象编程(OOP)是我们编程的一项基本技能,PHP5对OOP提供了良好的支持.如何使用OOP的思想来进行P ...

  4. PHP面向对象(OOP)编程入门教程链接

    PHP官方学习OOP: http://php.net/manual/zh/oop5.intro.php 从其他博主学习:(以下链接来源: http://blog.snsgou.com/post-41. ...

  5. 【PHP面向对象(OOP)编程入门教程】2.什么是类,什么是对象,类和对象这间的关系

    类的概念:类是具有相同属性和服务的一组对象的集合.它为属于该类的所有对象提供了统一的抽象描述,其内部包括属性和服务两个主要部分.在面向对象的编程语言中,类是一个独立的程序单位,它应该有一个类名并包括属 ...

  6. lua中 table 重构index/pairs元方法优化table内存占用

    转载请标明出处http://www.cnblogs.com/zblade/ lua作为游戏的热更新首选的脚本,其优势不再过多的赘述.今天,我主要写一下如何重写lua中的元方法,通过自己的重写来实现对l ...

  7. PHP面向对象(OOP)编程入门教程————如何实例化对象?

    我们上面说过面向对象程序的单位就是对象,但对象又是通过类的实例化出来的,既然我们类会声明了,下一步就是实例化对象了. 当定义好类后,我们使用new关键字来生成一个对象. $对象名称 = new 类名称 ...

  8. js面向对象oop编程

    理解对象 对象这个词如雷贯耳,同样出名的一句话:XXX语言中一切皆为对象! 对象究竟是什么?什么叫面向对象编程? 对象(object),台湾译作物件,是面向对象(Object Oriented)中的术 ...

  9. 【PHP面向对象(OOP)编程入门教程】23.自动加载类 __autoload()函数

    很多开发者写面向对象的应用程序时,对每个类的定义建立一个 PHP 源文件.一个很大的烦恼是不得不在每个脚本(每个类一个文件)开头写一个长长的包含文件的列表. 在软件开发的系统中,不可能把所有的类都写在 ...

随机推荐

  1. Linux音频编程指南

    Linux音频编程指南 虽然目前Linux的优势主要体现在网络服务方面,但事实上同样也有着非常丰富的媒体功能,本文就是以多媒体应用中最基本的声音为对象,介绍如何在Linux平台下开发实际的音频应用程序 ...

  2. Ubuntu 14.04快速搭建SVN服务器及日常使用【转】

    转自:http://www.linuxidc.com/Linux/2015-05/117735.htm 1.介绍  Subversion是一个自由,开源的版本控制系统,这个版本库就像一个普通的文件服务 ...

  3. url重写(伪静态)IIS配置图解

    通过IIS创建虚拟目录,新建网站放在该目录下面: IIS配置: 虚拟目录=>点击右键=>选择属性: 点击配置: 点击编辑: 复制两个文本框文本到记事本中=>点击确定: 点击添加=&g ...

  4. mysql高可用方案比较

    详见:High Availability Database Tools http://www.acquia.com/blog/high-availability-database-tools

  5. 第一篇 ERP是什么?-从道的层面浅谈我的理解

    世界上称为ERP软件的软件很多,国外的有SAP,ORACLE,国内的有金蝶,用友,浪潮.这些由不同的厂商开发制作的软件总有其软件适用的场合.这个场合就是企业,而且是市场经济中的企业.个人是不会购买ER ...

  6. C# treeview控件部分节点添加checkbox

    一.先初始化treeview this.treeView1.CheckBoxes = true; this.treeView1.ShowLines = false; this.treeView1.Dr ...

  7. Gradle学习系列(一)

    今天就开始学习Gradle构建了,听说很牛X.本篇内容就带领我初步窥探Gradle的世界.     1.什么是Gradle       相信之前都接触过用Ant或者Meavn进行项目的构建,两者各有千 ...

  8. Python3 学习第五弹:类与面向对象

    对于面向对象总是要提到,万物皆对象.好似博大精深的感觉. 接下来一起看看python的面向对象的例子 创建一个对象 class Person: type = 'person' def __init__ ...

  9. js案例_下滑列表

    1.HTML布局(使用ul): <body> <ul> <li class="list" id="lis"> <a h ...

  10. LA 4670 (AC自动机 模板题) Dominating Patterns

    AC自动机大名叫Aho-Corasick Automata,不知道的还以为是能自动AC的呢,虽然它确实能帮你AC一些题目.=_=|| AC自动机看了好几天了,作用就是多个模式串在文本串上的匹配. 因为 ...