对象的特点是:

  对象拥有自己的数据,两个对象即使数据完全相同,他们也是相互独立的;

  对象之间可以共享对象的行为,也就是他们的方法是一致的;

lua中的table就非常适合作为一个对象,可以在table中方便的定义属性和方法:

  Point = { x = 0, y = 0 }

  Point.set = function (x, y)

    Point.x = x

    Point.y = y

  end

  Point.set(1, 2)

但是要符合面相对象的规则,方法可以操作不同的对象,而不是同一个特定对象,我们可以将需要操作的对象作为参数传入:

  Point = {}

  Point.set = function (pt, x, y)

      pt.x = x

      pt.y = y

    end

  local pt1 = { x = 0, y = 0 }

  Point.set(pt, 1, 2)

我们可以将所有方法定义在一个集合中,然后在调用的时候将第一个参数作为对象传入即可。不过传统的面向对象是可以隐藏对象这个参数,而直接使用this代替,lua也提供了一种类似的操作,就是“:”操作符:

  Point = {}

  function Point:set (x, y) // 等价于 function Point.set(self, x, y)

    self.x = x

    self.y = y

  end

  Point:set(1, 2) // 等价于Point.set(Point, 1, 2)

这里冒号操作符的作用就是省略了第一个参数self,self是代表冒号之前的那个对象。.操作符和:操作符是可以随意互换的,只要在调用的时候确定参数的正确性即可,因为冒号操作符并没有引入新的东西,只是一种“语法糖”而已。

类是创建对象的模版,同一个类型的所有对象都具有相同的行为。

在lua中,如何创建一个类?lua中使用table来创建一个类,然后所有实例的元表都可以设置为这个类,即相同类型的对象具有相同的元表:

创建一个Point类:

  Point = {}

  function Point.new (x, y)

    local instance = {} // 创建一个实例

    setmetatable(instance, Point) // 设置所有实例的元表都是Point,所以实例的方法都会去Point中查找

    Point.__index = Point // 同时必须设置__index元方法为Point,因为实例的所有方法,我们都会定义在Point中

    instance.x = x

    instance.y = y

    return instance

  end

添加类的方法:

  function Point:set (x, y)

    self.x = x

    self.y = y

  end

  function Point:get ()

    return {x, y}

  end

使用:

  local pt = Point.new(1, 2)

  pt:set(3, 4)

  local data = pt:get()

类的继承:根据lua的table特性,如果一个字段在table中不存在,那么lua回去尝试调用元表的__index元方法,如果元方法是一个table,那么该规则会持续下去,直到找到一个定义或者搜索结束。这种机制就类似一个链式结构,这个链式结构就形成了一个继承关系。子类不存在某个方法的时候,总是会向父类去寻找,依次类推。

从Point类继承一个子类Point3D:

  Point3D = {}

  function Point3D:new (x, y, z)

    local instance = Point:new(x, y) // 创建一个父类对象,继承了父类所有的属性

    instance.z = z

    setmetatable(Point3D, Point) // 设置子类Point3D的元表为父类Point

    Point3D.__index = Point3D // 设置元方法为自己

    setmetatable(instance. Point3D) // 设置instance的元表为Point3D

    return instance  

  end

重写父类的方法:

  function Point3D:set (x, y, z)

    Point.set(self, x, y)

    self.z = z

  end

实现自己的方法:

  function Point3D:setZ (z)

    self.z = z

  end

甚至为instace实现特有的方法:

   function instance:print()

    print("it is a printer for instance ", self)

  end

使用:

  local pt3d = Point3D:new(1, 2, 3)

  pt3d:set(4, 5, 6)

  pt3d:setZ(10)

  pt3d:print()

这样实现后,就形成了instance -> Point3D -> Point 的链式结构,lua会按照这个顺序依此搜索方法,调用最先找到的方法。

实例:

Point.lua

  1. --#! /usr/local/bin/lua
  2.  
  3. Point = {}
  4. Point.__index = Point;
  5.  
  6. local POINT_PROPS = {
  7. x = ,
  8. y =
  9. }
  10.  
  11. function Point:new(x, y)
  12. local instance = {}
  13. for k, v in pairs(POINT_PROPS) do
  14. instance[k] = v
  15. end
  16. instance.x = x
  17. instance.y = y
  18.  
  19. setmetatable(instance, Point)
  20.  
  21. return instance
  22. end
  23.  
  24. function Point:set (x, y)
  25. print("Point set x:"..x.." y:"..y)
  26.  
  27. self.x = x
  28. self.y = y
  29. end
  30.  
  31. function Point.get (self)
  32. print("Point get x:"..self.x.." y:"..self.y)
  33.  
  34. return {x, y}
  35. end

Point3D.lua

  1. --#! /usr/local/bin/lua
  2.  
  3. require "Point"
  4.  
  5. Point3D = {}
  6. Point3D.__index = Point3D;
  7.  
  8. local POINT3D_PROPS = {
  9. z =
  10. }
  11.  
  12. function Point3D:new (x, y, z)
  13. local instance = Point:new(x, y)
  14. for k, v in pairs(POINT3D_PROPS) do
  15. instance[k] = v
  16. end
  17. instance.z = z
  18.  
  19. setmetatable(Point3D, Point)
  20. setmetatable(instance, Point3D)
  21.  
  22. return instance
  23. end
  24.  
  25. function Point3D:set (x, y, z)
  26. print("Point3D set x:"..x.." y:"..y.." z:"..z)
  27.  
  28. Point.set(self, x, y)
  29. self.z = z
  30. end
  31.  
  32. function Point3D:setZ (z)
  33. print("Point3D setZ z:"..z)
  34.  
  35. self.z = z
  36. end
  37.  
  38. function Point3D:get ()
  39. print("Point3D get x:"..self.x.." y:"..self.y.." z:"..self.z)
  40. end

test.lua

  1. require "Point3D"
  2.  
  3. local pt = Point3D:new(, , );
  4. for k, v in pairs(pt) do
  5. print(k, v)
  6. end
  7. pt:set(, , )
  8. pt:get()
  9.  
  10. function pt:print()
  11. print("pt", self.x, self.y, self.z, self)
  12. end
  13.  
  14. pt:print()

多重继承:

  为了实现多重继承,就无法为对象设置一个父类作为元表,必须将多个父类保存起来,然后设置一个元方法__index为函数,在函数调用的时候,在多个父类中为对象寻找适合的方法。

Color.lua

  1. Color = {}
  2.  
  3. function Color:setColor (r, g, b, a)
  4. self.r = r
  5. self.g = g
  6. self.b = b
  7. self.a = a
  8. end
  9.  
  10. function Color:getColor ()
  11. print("color r:"..self.r.." g:"..self.g.." b:"..self.b.." a"..self.a)
  12.  
  13. return {self.r, self.g, self.b, self.a}
  14. end

test.lua

  1. require "Point"
  2. require "Color"
  3.  
  4. ColorPoint = {}
  5. ColorPoint.__interfaces = { Point, Color }
  6. ColorPoint.__index = function (t, key)
  7. local interfaces = ColorPoint.__interfaces;
  8.  
  9. for i = , #interfaces do
  10. local func = interfaces[i][key]
  11. if func then return func end
  12. end
  13. return nil
  14. end
  15.  
  16. function ColorPoint:new ()
  17. local instance = {}
  18. setmetatable(instance, ColorPoint)
  19. return instance
  20. end
  21.  
  22. local cp = ColorPoint:new()
  23. local cp1 = ColorPoint:new()
  24.  
  25. cp:set(, )
  26. cp:get()
  27. cp:setColor(, , , )
  28. cp:getColor()

单列模式,利用了闭包的原理,将数据隐蔽起来:

  1. local _instance = {}
  2.  
  3. local filelist = {}
  4. local fileCount =
  5.  
  6. local isExist = function (filename)
  7. return not (filelist[filename] == nil)
  8. end
  9.  
  10. function _instance:load (filename)
  11. if (isExist(filename)) then print(filename) return end
  12.  
  13. local file = io.open(filename)
  14.  
  15. if (file) then
  16. io.input(file)
  17. local data = assert(io.read("*all"))
  18. filelist[filename] = data
  19.  
  20. fileCount = fileCount +
  21.  
  22. io.close(file)
  23. else
  24. error("FileManager load file "..filename.." failed")
  25. end
  26. end
  27.  
  28. function _instance:getFileCount ()
  29. return fileCount
  30. end
  31.  
  32. function _instance:getFileData (filename)
  33. return filelist[filename]
  34. end
  35.  
  36. function _instance:removeFileData (filename)
  37. if (filelist[filename]) then
  38. filelist[filename] = nil
  39. fileCount = fileCount -
  40. end
  41.  
  42. assert(fileCount >= , "FileManager removeFileData file count error")
  43. end
  44.  
  45. function _instance:isExist (filename)
  46. return not (filelist[filename] == nil)
  47. end
  48.  
  49. FileManager = {
  50. getInstance = function()
  51. return _instance
  52. end
  53. }
  54. _G["FileManager"] = FileManager
  55. return FileManager
  1. FileManager:getInstance():load("1.txt")
  2. FileManager:getInstance():load("2.txt")
  3. print(FileManager:getInstance():getFileCount())
  4. print(FileManager:getInstance():getFileData("1.txt"))
  5. FileManager:getInstance():removeFileData("1.txt")
  6. print(FileManager:getInstance():getFileCount())
  7. print(FileManager:getInstance():getFileData("1.txt"))
  8. print(FileManager:getInstance():getFileData("2.txt")

lua 面向对象的更多相关文章

  1. Lua面向对象----类、继承、多继承、单例的实现

    (本文转载)学习之用,侵权立删! 原文地址   http://blog.csdn.net/y_23k_bug/article/details/19965877?utm_source=tuicool&a ...

  2. Lua面向对象之三:其它一些尝试

    1.尝试一:子类对象调用被覆盖了的父类函数 根据元表设置流程,我们只有将父类元表找到就能调用父类的方法了 ①在子类Circle中增加一个调用父类方法的函数 --调用父类被子类覆盖了的name方法 fu ...

  3. Lua面向对象之二:类继承

    1.类继承 ①代码 Sharp = { } --① 父类 function Sharp:new() local new_sharp = { } self.__index = self --②,self ...

  4. Lua面向对象之一:简单例子

    1.Lua面向对象实现步骤 ①创建一个全局表(称之为元表) ②设置这个元表的__index值(值通常为元表自己,这样就能通过__index查找到对应的属性和方法) __index 赋值其实是一个fun ...

  5. lua面向对象封装

    lua面向对象的一个封装,直接贴代码 --swfclass = {};local cs = {};function _class( child, base, ... )--    _.s( child ...

  6. lua面向对象实现(实例化对象、继承、多态、多继承、单例模式)

    lua面向对象实现: 一个类就像是一个创建对象的模具.有些面向对象语言提供了类的概念,在这些语言中每个对象都是某个特定类的实例.lua则没有类的概念,每个对象只能自定义行为和形态.不过,要在lua中模 ...

  7. Step By Step(Lua面向对象)

    Step By Step(Lua面向对象) Lua中的table就是一种对象,但是如果直接使用仍然会存在大量的问题,见如下代码: 1 Account = {balance = 0}2 function ...

  8. Lua面向对象

    lua中的table就是一种对象,但是如果直接使用仍然会存在大量的问题,如下: 1 Account = {balance = 0}2 function Account.withdraw(v)3 Acc ...

  9. Lua面向对象设计

    首先对于Lua语言,它没有打算被用来进行大型的程序设计,相反,Lua目标定于小型到中型的程序设计,通常是作为大型系统的一部分,所以它只提供了一套精简的元素,很多高级语言的概念都没有.这样Lua就成为了 ...

随机推荐

  1. android基础(二)Broadcast Receiver知识

    1.广播的注册 (1)动态广播注册: 优点:可以灵活控制广播的注册与撤销 缺点:必须在程序启动时才能接收广播 IntentFilter :当Intent在组建之间传递时,组件想告诉android系统自 ...

  2. 帐户当前被锁定,所以用户 sa 登录失败。系统管理员无法将该帐户解锁 解决方法

    ALTER LOGIN sa ENABLE ; GO ALTER LOGIN sa WITH PASSWORD = 'password' unlock, check_policy = off, che ...

  3. TCP 状态机

    TCP 状态机 TCP 协议的操作可以使用一个具有 11 种状态的有限状态机( Finite State Machine )来表示,图 3-12 描述了 TCP 的有限状态机,图中的圆角矩形表示状态, ...

  4. 字体Unicode编码

    客专家福利     有奖试读&征文——我们在互联网上奋斗的故事      10月推荐文章汇总      加入“技术热心人”,赢丰厚奖品 html-中文字体在CSS中的显示(Unicode编码) ...

  5. RocketMQ生产者示例程序

    转载请注明出处:http://www.cnblogs.com/xiaodf/ 本示例展示了一个RocketMQ producer的简单实现,通过解析文本文件获取输入数据,将数据经过Avro序列化后发送 ...

  6. 自定义EditText实现可以一键删除输入的内容

    public class MyEditText extends EditText { private Drawable dRight; private Rect rRounds; public MyE ...

  7. asp.net 前台通过Eval()绑定动态显示样式

    1.a标签链接 <%#Eval("ConfigCode").ToString().ToLower() == "publishtext" ? "& ...

  8. Windows 下的 Sublime Text 2 配置汇总, Sublime Text 3 亦可借鉴

    1)软件下载地址:http://www.sublimetext.com/2 2)安装 Package Control ,方便安装和管理插件,网络资源很多,这里附上一篇:http://www.imjef ...

  9. Django 的开始之路

    django源码安装 检查是否安装成功 1.在命令行进入Django环境 在新建完项目后 进入带有manage.py的目录,执行以下文件. python manage.py  shell 2.Djan ...

  10. eclipse平台

    eclipse 是一个平台!!!! 能连ssh,能连db,能连windows Eclipse http://www.eclipse.org/downloads/packages/release/Neo ...