1 Lua中的面向对象

1.1 问题

lua不是一个面向对象的语言。可是他又有面向对象的思想。

lua中的面向对象是伪面向对象。伪面向对象就要用到table实现。

由table模拟了一个面向对象的编程, table事实上也能够看做是一个对象。和其它语言对象一样有个自身的标示(self),具有自己的生命周期。本案例演示lua中的面向对象。

1.2 方案

首先用table实现面向对象。

然后通过self得到当前lable对象。

接下来通过 : 符号实现声明函数时的隐试參数self。

最后通过require返回对象,调用该对象方法。

1.3 步骤

实现此案例须要依照例如以下步骤进行。

步骤一:用table实现面向对象

首先定义一个table类型的数据Account。然后声明label对象。通过对象调用方法,代码例如以下所看到的:

  1. Accout = {balance = 0}
  2. functionAccout.count( v )
  3. print ("value is "..v)
  4. end
  5. --声明label对象(变量)accout
  6. accout = Accout
  7. --通过对象调用方法
  8. accout.count(1000)

编辑器中的效果如图-13所看到的:

图-13

步骤二:通过self得到当前lable对象

通过对象调用方法。显示的把accout这个table 这个对象传入到函数 (显示的传入 self),还可通过冒号调用的方式隐试的传入self对象代码例如以下所看到的:

  1. Accout = {balance = 10}
  2. --显示传入self
  3. functionAccout.count( self, v )
  4. self.balance = self.balance + v;
  5. print ("value is "..self.balance)
  6. end
  7. --声明label对象(变量)accout
  8. accout = Accout
  9. --通过对象调用方法, 显示的把accout这个 table 这个对象传入到函数 (显示的传入 self)
  10. accout.count(accout, 1000)
  11. --还可通过 : 调用的方式隐试的传入 self 对象
  12. accout:count(2000)

编辑器中的效果如图-14所看到的:

图14

步骤三:通过冒号实现声明函数的隐式參数

通过冒号符号隐式传入self。还可通过冒号调用的方式隐式的传入self对象,代码例如以下所看到的:

  1. Accout = { balance = 10}
  2. --通过 : 符号, 隐试传入 self
  3. functionAccout:count( v )
  4. self.balance = self.balance + v;
  5. print ("value is "..self.balance)
  6. end
  7. --声明label对象(变量)accout
  8. accout = Accout
  9. --还可通过 : 调用的方式隐试的传入 self 对象
  10. accout:count(2000)

编辑器中的效果如图-15所看到的:

图-15

步骤四:通过require 返回对象

通过require 返回对象,调用该对象方法,代码例如以下所看到的:

  1. class = require("myClass")
  2. --函数写在 table的括号外
  3. class:showName()
  4. --函数写在 table的括号内
  5. class.show(class)

编辑器中的效果如图-16所看到的:

图-16

-------------》require(“XXX”)  --  仅仅运行一次,避免了反复运行

1.4 完整代码

本案例中。完整代码例如以下所看到的:

  1. --[[lua不是一个面向对象的语言。可是他又有面向对象的思想
  2. lua中的面向对象是伪面向对象,伪面向对象就要用到table实现。
  3. 是table模拟了一个面向对象的编程。 table事实上也能够看做是一个对象,
  4. 和其它语言对象一样有个自身的标示(self)。具有自己的生命周期。]]
  5. --1.用table实现面向对象
  6. Accout = {balance = 0}
  7. functionAccout.count( v )
  8. print ("value is "..v)
  9. end
  10. --声明label对象(变量) accout
  11. accout = Accout
  12. --通过对象调用方法
  13. accout.count(1000)
  14. --2.通过 self 得到当前 lable 对象
  15. Accout = {balance = 10}
  16. --显示 传入 self
  17. functionAccout.count( self, v )
  18. self.balance = self.balance + v;
  19. print ("value is "..self.balance)
  20. end
  21. --声明label对象(变量) accout
  22. accout = Accout
  23. --通过对象调用方法, 显示的把 accout 这个 table 这个对象传入到函数 (显示的传入 self)
  24. accout.count(accout, 1000)
  25. --还可通过 : 调用的方式 隐试的传入 self 对象
  26. accout:count(2000)
  27. --3.通过 : 符号,实现声明函数时的 隐试參数 self
  28. Accout = { balance = 10}
  29. --通过 : 符号, 隐试 传入 self
  30. functionAccout:count( v )
  31. self.balance = self.balance + v;
  32. print ("value is "..self.balance)
  33. end
  34. --声明label对象(变量) accout
  35. accout = Accout
  36. --还可通过 : 调用的方式 隐试的传入 self 对象
  37. accout:count(2000)
  38. --4.通过require 返回对象, 调用该对象方法
  39. class = require("myClass")
  40. --函数写在 table的括号 外
  41. class:showName()
  42. --函数写在 table的括号 内
  43. class.show(class)
2、元方法与元表
元方法:就是两个 类型 变量之间进行操作的 函数
比如,1.数字的相加。它可能不过一个函数:1 + 1--->add(1,1)--->add函数就是用来计算两个数字间相加的结果de
2.table类型相加?--->Lua中不存在两个{} + {}的元方法。
元表(metatable):就是用来存放 元方法 的 table,是table提前定义的一系列操作。把两个table相加,那么Lua就会先去检查两个table是否有metatable,然后再检 查metatable中是否有__add方法。 假设有依照__add方法中的操作来运行,否则,报错。
比如,假设非要将两个table类型相加的话,直接执行必报错。 但Lua同意改动元表,例如以下所看到的:
一个元表,事实上就是一个table值,所以,我们仅仅须要新建一个table,加入元方法就可以。 比方加法运算的元方法就是:__add,这是Lua规定的。 仅仅要某个值的元表里含有__add这个元方法。那就能够使用+号进行运算。 例如以下代码:
  1. -- 创建一个元表
  2. local mt = {};
  3. mt.__add = function(t1, t2)
  4. print("两个table相加的结果就是...Good Good Study,Day Day Up!");
  5. end
  6. local t1 = {};
  7. local t2 = {};
  8. -- 给两个table设置新的元表
  9. setmetatable(t1, mt);
  10. setmetatable(t2, mt);
  11. -- 进行加法操作
  12. local result = t1 + t2;

首先创建了一个table变量mt,给这个table新增一个元素__add。这个table就拥有了作为元表的资格了。

然后创建两个新的table变量。使用setmetatable函数给table设置新的元表。此时,两个table变量就以mt作为元表了。

最后,对t1和t2进行加法操作。这时就会从元表中查找__add元方法。假设找到的话,就调用这个元方法对两个变量进行加法操作。

Lua中的每个值都有或者能够有一个元表,但table和userdata能够拥有独立的元表,其它类型的值就仅仅能共享其类型所属的元素。比方字符串使用的是
string的元表。注意:Lua在新建table时,不会创建metatable,须要使用setmetatable来设置元表。setmetatable的參数能够使随意table,包含要赋值的table本身。


------》查看一个变量是否有元表:
print(getmetatable(a)) -- nil 表示没有元表


Lua中的重要的元方法:__eq等于、__lt小于、__le小于等于、__add:加法、__sub:减法、__mul:乘法、__div:除法、__unm:相反数、__mod:取模、__pow:乘幂、__index function(table,key)、__newindex function(table,key,value)、__tostring 被print()调用、__metatable设置后可隐藏mt

仅仅要在自己定义元表的时候,给这些元方法名赋予新的函数就能够实现自己定义操作了。

Lua訪问table元素 首先。通过__index元方法来查找是否有这个函数(假设没有。返回nil);__index的值能够直接是一个table。也能够是函数(若是table,则以该table作为索引进行查询。若是函数。则将table和缺少的域作为參数,调用这个函数)

样例1、

我们新建一个自己定义的元表(也就是一个table变量)。用来定义一些操作:

  1. -- 创建一个元表
  2. local mt = {};
  3. mt.__add = function(s1, s2)
  4. local result = "";
  5. if s1.sex == "boy" and s2.sex == "girl" then
  6. result = "青梅竹马";
  7. elseif s1.sex == "girl" and s2.sex == "girl" then
  8. result = "空对空";
  9. else
  10. result = "硬碰硬"
  11. end
  12. return result;
  13. end

事实上这和上一节的样例基本一样。仅仅是多说一次而已,使用方式例如以下:

  1. -- 创建两个table,能够想象成是两个类的对象
  2. local s1 = {
  3. name = "Hello",
  4. sex = "boy",
  5. };
  6. local s2 = {
  7. name = "Good",
  8. sex = "girl",
  9. };
  10. -- 给两个table设置新的元表
  11. setmetatable(s1, mt);
  12. setmetatable(s2, mt);
  13. -- 进行加法操作
  14. local result = s1 + s2;
  15. print(result);
样例2、
Window = {}
Window.mt = {}
Window.prototype = {x = 0,y = 0,width = 100,height = 100}
Window.mt.__index = function(table,key)
return Window.prototype[key]
end
function Window.new(t)
setmetatable(t,Window.mt)
return t
end
--測试
w = Window.new{x = 10,y = 20}
print(w.heigth)
__newindex的使用方法基本与样例2一致。差别在于__newindex的作用是用于table的更新,__index用于table的查询操作。
当对table中不存在的索引赋值时,就会调用__newindex元方法。组合使用__index和__newindex能够实现非常多功能
封装:
有了元表(metatable)之后。Lua类的封装就会变得非常easy。仅仅要为table加入metatable,并设置__index方法。
比如:
People = {age = 18}
function People:new()
local p = {}
setmetatable(p,self)
self.__index = self
return p
end
function People:groupUp()
self.age = self.age + 1
print(self.age)
end
--測试
p1 = People:new()
p1:growUp() --19
p2 = People:new()
p2:growUp() --19
--[[执行结果能够看出:两个对象拥有的age成员是全然独立的。并且全部的有关People的方法都能够对外不可见,这样全然实现了面向对象中的类的封装--]]
继承:
继承是面向对象中不可缺少的一部分。依旧使用上例中的People,展示Lua中实现继承的方法。 创建一个People实例Man,再在Man上重写People的同名方法:
Man = People:new()
function Man:growUp()
self.age = self.age + 1
print("man's growUp:"..self.age)
end
--測试
man1 = Man:new()
man1.growUp() --man's growUp:19
多态:
Lua不支持函数多态,而支持指针的多态,因为Lua动态类型的特性,本身就能支持。
person = People:new()
person:growUp() --People's growUp:19
person = Man:new()
person:growUp() --Man's growUp:19

cocos2d-Lua02Lua面向对象的更多相关文章

  1. Cocos2d Lua 越来越小样本 内存游戏

    1.游戏简介 一个"记忆"类的比赛游戏.你和电脑对战,轮到谁的回合,谁翻两张牌,假设两张牌一样.就消掉这两张牌,得2分,能够继续翻牌,假设两张牌不一样,就换一个人.直到最后.看谁的 ...

  2. angular2系列教程(六)两种pipe:函数式编程与面向对象编程

    今天,我们要讲的是angualr2的pipe这个知识点. 例子

  3. 一起学 Java(二)面向对象

    一.方法函数 函数也称为方法,就是定义在类中的具有特定功能的一段独立代码.用于定义功能,提高代码的复用性. 函数的特点1> 定义函数可以将功能代码进行封装,便于对该功能进行复用:2> 函数 ...

  4. js面向对象学习 - 对象概念及创建对象

    原文地址:js面向对象学习笔记 一.对象概念 对象是什么?对象是“无序属性的集合,其属性可以包括基本值,对象或者函数”.也就是一组名值对的无序集合. 对象的特性(不可直接访问),也就是属性包含两种,数 ...

  5. 前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型

    前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型 前言(题外话): 有人说拖延症是一个绝症,哎呀治不好了.先不说这是一个每个人都多多少少会有的,也不管它究竟对生活有多么大的 ...

  6. .NET 基础 一步步 一幕幕[面向对象之对象和类]

    对象和类 本篇正式进入面向对象的知识点简述: 何为对象,佛曰:一花一世界,一木一浮生,一草一天堂,一叶一如来,一砂一极乐,一方一净土,一笑一尘缘,一念一清静.可见"万物皆对象". ...

  7. 简单分析JavaScript中的面向对象

    初学JavaScript的时候有人会认为JavaScript不是一门面向对象的语言,因为JS是没有类的概念的,但是这并不代表JavaScript没有对象的存在,而且JavaScript也提供了其它的方 ...

  8. Java程序员应该了解的10个面向对象设计原则

    面向对象设计原则: 是OOPS(Object-Oriented Programming System,面向对象的程序设计系统)编程的核心,但大多数Java程序员追逐像Singleton.Decorat ...

  9. JavaScript学习笔记(三)——this、原型、javascript面向对象

    一.this 在JavaScript中this表示:谁调用它,this就是谁. JavaScript是由对象组成的,一切皆为对象,万物皆为对象.this是一个动态的对象,根据调用的对象不同而发生变化, ...

  10. 带你一分钟理解闭包--js面向对象编程

    上一篇<简单粗暴地理解js原型链--js面向对象编程>没想到能攒到这么多赞,实属意外.分享是个好事情,尤其是分享自己的学习感悟.所以网上关于原型链.闭包.作用域等文章多如牛毛,很多文章写得 ...

随机推荐

  1. [hihoCoder] 第四十九周: 欧拉路·一

    题目1 : 欧拉路·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho最近在玩一个解密类的游戏,他们需要控制角色在一片原始丛林里面探险,收集道具,并找到最 ...

  2. Android 架构师技能图谱(转载)

    架构与设计 设计模式 重构 技术选型 特性 可用性 性能 包大小 方法数 文档 技术支持 UI架构模式 MVC MVP MVVM 研发工具 集成开发环境 Android Studio Sublime ...

  3. 全局获取 (Activity)Context,实现全局弹出 Dialog

    为什么需要一个全局的 (Activity)Context 需求1:在进入 app 的时候,要求做版本检测,有新的版本的时候,弹出一个 AlertDialog,提示用户版本更新 需求2:从别的设备挤下来 ...

  4. Android:相机适配及图片处理的一些问题

    链接:http://www.cnblogs.com/liushilin/p/6387263.html 链接:http://www.cnblogs.com/liushilin/p/5956691.htm ...

  5. C#判断访问网站的设备类型

    同样也是在破解版的HISHOP源码上扒出来的,代码如下: protected void InitVisitorTerminal()        {            VisitorTermina ...

  6. spark repartition

    https://jaceklaskowski.gitbooks.io/mastering-apache-spark/content/spark-rdd-partitions.html http://s ...

  7. Mac终端中主机名与用户名的修改

    Mac终端的主机名称+用户名全部显示出来的话会可能显得特别长,影响整体美观,可以切换至root用户后 修改.bashrc文件进行格式化. 1. 终端中切换root用户 su - root 2. 修改/ ...

  8. c#多线程 Invoke方法的使用

    在多线程编程中,我们经常要在工作线程中去更新界面显示,而在多线程中直接调用界面控件的方法是错误的做法,Invoke 和 BeginInvoke 就是为了解决这个问题而出现的,使你在多线程中安全的更新界 ...

  9. ubuntu中gitlab搭建

    1.gitlab介绍 gitlab是一款代码仓库管理工具,可以用来搭建自己的代码管理服务器. gitlab包自带了redis,nginx,postgresql,unicorn等众多服务组件. 2.硬件 ...

  10. 【DIOCP3-说明书】DIOCP3的输出日志

    DIOCP3除了有详细的监控面板之外,还有详细的输出日志,当然需要打开日志编译开关! 在工程选项加入DEBUG编译指令,这样在运行中就可以看到DIOCP3的运行详细日志 日志输出在EXE相同目录的LO ...