首先对于Lua语言,它没有打算被用来进行大型的程序设计,相反,Lua目标定于小型到中型的程序设计,通常是作为大型系统的一部分,所以它只提供了一套精简的元素,很多高级语言的概念都没有。这样Lua就成为了一个既简单又灵活的轻量级语言,但是基本上高级语言中的大多数机制都可以在现有Lua的基础上加以实现。

  面向对象的基础是类,但Lua中没有提供类的概念,所以我们需要利用Lua现有的机制来实现类似于类的有关oop的一整套概念。基本方案是使用table来实现类机制,并且结合使用self参数和冒号操作。我们先来看看self参数和冒号操作符的用法:

  self参数的使用是很多面向对象语言的要点,大多数OO语言将这种机制隐藏起来,这样程序员不必声明这个参数(虽然仍然可以在方法内使用这个参数)。Lua也提供了通过使用冒号操作符来隐藏这个参数的声明(通过冒号来声明函数)。先来看下这段代码(这里面还不涉及到类的定义,只是纯粹为了解释self和冒号操作):

  1. Account = {balance = 0}
  2.  
  3. function Account.withdraw(obj, v)
  4. obj.balance = obj.balance + v
  5. end
  6.  
  7. a = Account
  8. a.withdraw(a, 100)
  9. print(a.balance)

  也可以将函数写成这样(将obj换成self能更好的表达出该参数的语义):

  1. function Account.withdraw(self, v)
  2. self.balance = self.balance + v
  3. end

  self本身是一个Lua的保留字,为了不必给每个函数声明都加上self,Lua提供了冒号操作符:

  1. function Account:withdraw (v)
  2. self.balance = self.balance - v
  3. end

  定义函数时将点改成冒号,函数体内部直接用self参数访问对象自己(self参数表示表自己,也就是对象本身)。同时函数调用也有两种写法,并且这两种写法是通用的:

  1. a.withdraw(a, 100)
  2. a:withdraw(100)

  点操作需要显示传入调用者自身。实际上,冒号的效果相当于在函数定义和函数调用的时候,增加一个额外的隐藏参数。这种方式只是提供了一种方便的语法,并没有什么新的内容。我们可以使用dot语法定义函数而用冒号语法调用函数,反之亦然,只要我们正确的处理好额外的 参。

  Lua中的表其实是一个对象。我们定义一个表作为原型(相当于类定义),然后其他的对象(也是一个表)通过metatable和__index机制来访问原型表中的成员。下面看下类的实现:

  1. Account = {balance = 0}
  2.  
  3. --将表自己做成metatable,或者也可以在表中加入一个mt成员来作为metatable
  4. function Account:new(o)
  5. o = o or {}
  6. setmetatable(o, self)
  7. self.__index = self
  8. return o
  9. end
  10.  
  11. function Account:withdraw(v)
  12. self.balance = self.balance - v
  13. end
  14.  
  15. function Account:deposit(v)
  16. self.balance = self.balance + v
  17. end
  18.  
  19. a1 = Account:new{}
  20. a2 = Account:new{balance = 100}
  21. a1:withdraw(100)
  22. print(a1.balance)
  23. print(a2.balance)

  为了简洁,直接将类本身定为对象表的metatable。上面的new函数还是有一定的技巧性的,之前用过C++/Java等语言的人,应该不太习惯这种写法。因为在强类型语言中,编程者会尽量避免倾向于展示技巧的写法,而使用更简单、可读性更高的写法。但在使用Lua时需要转换一下思维,尤其是在基于Lua基础的东西来扩展一些概念的时候,各种技巧性的东西会很常见,要习惯。

  类继承的实现其实很简单,直接调用基类的new操作,然后在子类中可以添加一些新的成员或方法:

  1. -- 继承自Account的类(其实就是一个Account对象),SpecialAcount可以重新定义继承来的成员函数,或添加新的成员函数
  2. SpecialAccount = Account:new()
  3.  
  4. -- 子类实例化,有趣之处是,smetatableSpecialAccount
  5. s = SpecialAccount:new{limit = 1000}

  可以看到,其实上面的类也是对象,只是看你怎么去理解它,当把一个对象当做模板原型来用时,它就是一个类,但同时,它也是一个对象,很随意有木有。

  多继承:多继承的想法很简单,就是对于子类中不存在的域,在多个父类中依次查找即可。不过此代码有点复杂,如下所示:

  1. Named = {name = "default"}
  2. function Named:getname() return self.name end
  3. function Named:setname(v) self.name = v end
  4.  
  5. --k为函数名,list为父类列表
  6. search = function(k, list)
  7. for i = 1, table.getn(list) do
  8. local v = list[i][k] -- 访问第i个父类的k域,存在则返回
  9. if v then return v end
  10. end
  11. end
  12.  
  13. -- 参数为父类列表
  14. createClass = function (...)
  15. c = {}
  16.  
  17. -- 这里面的k为访问的域
  18. setmetatable(c, {__index = function(t, k) return search(k, arg) end})
  19.  
  20. -- 用作对象的metatable
  21. c.__index = c
  22. function c:new(o)
  23. o = o or {}
  24. setmetatable(o, c)
  25. return o
  26. end
  27.  
  28. return c
  29. end
  30.  
  31. NamedAccount = createClass(Account, Named)
  32. obj = NamedAccount:new{name = "Paul"}
  33. print(obj:getname())

  函数search表示在父类列表list中依次查找名字为k的域。

  函数createClass用于创建多继承的类,参数为父类列表。可以看到对象以多继承类为metatable,而多继承类通过metatable在多个父类中依次查找域。

  私有成员的实现:基于闭包来封装掉不想被外部访问的数据或接口。

  1. function newAccount(initialBalance)
  2. -- 这里面放的全是私有部分,可以是私有数据或私有函数
  3. local self = {balance = initialBalance}
  4.  
  5. local withdraw = function(v) self.balance = self.balance - v end
  6. local deposit = function(v) self.balance = self.balance + v end
  7.  
  8. local getBalance = function() return self.balance end
  9.  
  10. -- 对外公开的接口全在return的表中索引
  11. return {withdraw = withdraw, deposit = deposit, getBalance = getBalance}
  12. end
  13.  
  14. a1 = newAccount(0)
  15. a2 = newAccount(100)
  16. a1.withdraw(100)
  17. print(a1.getBalance())
  18. print(a2.getBalance())

  一种特殊的“对象”:对象只有一个单一的方法时,可以这样使用。它是前面介绍的oop的一种特例,这种对象不具有继承性,但具有私有性,而且效率比较高:

  1. function newObject(value)
  2. return function(action, v)
  3. if action == "get" then return value
  4. elseif action == "set" then value = v
  5. else error("invalid action")
  6. end
  7. end
  8. end
  9.  
  10. d = newObject(0)
  11. print(d("get"))
  12. d("set", 10)
  13. print(d("get"))

  从上面可以看出这种Single-Method对象实际上就是一个闭包。它不使用表,而是将一个哈桉树看做一个对象。

http://www.cnblogs.com/sifenkesi/p/3845132.html

Lua面向对象设计(转)的更多相关文章

  1. Lua面向对象设计

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

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

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

  3. UML类图与面向对象设计原则

    1. 引言     从大一开始学习编程,到如今也已经有两年了.从最初学习的Html,Js,JaveSe,再到JavaEE,Android,自己也能写一些玩具.学习过程中也无意识的了解了一些所谓的设计模 ...

  4. 面向对象设计之SRP(单一职责)原则

    SRP设计原则面向对象类设计的第一个原则,最优先考虑的因素 一个类应该有且仅有一个职责.所谓一个类的职责是指引起该类变化的原因,如果一个类具有一个以上的职责,那么就会有多个不同的原因 引起该类变化,其 ...

  5. day24:面向对象设计与面向对象编程、类和对象

    一.三大编程范式: 面向过程: 面向函数: 面向对象: 二.程序的进化论: 1.编程最开始就是无组织无结构,从简单控制流中按步写指令 2.从上述的指令中提取重复的代码块或逻辑,组织到一起(比方说,你定 ...

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

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

  7. 【转】面向对象设计的SOLID原则

    S.O.L.I.D是面向对象设计和编程(OOD&OOP)中几个重要编码原则(Programming Priciple)的首字母缩写. SRP The Single Responsibility ...

  8. 6. javacript高级程序设计-面向对象设计

    1. 面向对象设计 1.1 理解对象 1.1.1 属性类型 (1). 数据属性:相当于对象的字段,包含一个数据值的位置,在这个位置可以读取和写入值.数据属性中有4个描述其行为的特性: l [[Conf ...

  9. 【OOAD】面向对象设计原则概述

    软件的可维护性和可复用性 知名软件大师Robert C.Martin认为一个可维护性(Maintainability) 较低的软件设计,通常由于如下4个原因造成: 过于僵硬(Rigidity)  ...

随机推荐

  1. dedecms 文章列表和频道列表同时调用

    演示效果:http://www.mypf110.com/qcd/ <div class="changshi_wrap"> {dede:channelartlist ro ...

  2. VSTO 学习笔记(十)Office 2010 Ribbon开发

    原文:VSTO 学习笔记(十)Office 2010 Ribbon开发 微软的Office系列办公套件从Office 2007开始首次引入了Ribbon导航菜单模式,其将一系列相关的功能集成在一个个R ...

  3. 跨平台网络通信与server编程框架库(acl库)介绍

    一.描写叙述 acl project是一个跨平台(支持LINUX,WIN32,Solaris,MacOS,FreeBSD)的网络通信库及server编程框架,同一时候提供很多其它的有用功能库.通过该库 ...

  4. atitit.高级编程语言的特性 and 未来趋势与进化.doc

    atitit.高级编程语言的特性 and 未来趋势与进化.doc 1 编程语言的发展历程 1 1.1 编程语言的进化,起始发现背后的思想 :不论什么两个系统之间的复杂性,都能够通过加入一个抽象层要屏蔽 ...

  5. 检查Linux Bash安全漏洞以及各环境修复解决方法

    第一.检测是否存在Bash漏洞$env x='() { :;}; echo vulnerable' bash -c "echo this is a test"如果返回以下内容:则请 ...

  6. Python 收集Twitter时间序列数据

    CODE: #!/usr/bin/python # -*- coding: utf-8 -*- ''' Created on 2014-7-18 @author: guaguastd @name: c ...

  7. C++设计模式之建造者模式(三)

    4.引入钩子方法的建造者模式 建造者模式除了逐步构建一个复杂产品对象外.还能够通过Director类来更加精细地控制产品的创建过程.比如添加一类称之为钩子方法(HookMethod)的特殊方法来控制是 ...

  8. Cocos2d-x Layout简单使用

    1. Text* alert = Text::create("Layout", "fonts/Marker Felt.ttf", 30 ); alert-> ...

  9. sublime text 2安装及使用

    1.首先下载Sublime Text:http://www.sublimetext.com/ 2.基本设置.參考此文:http://blog.jobbole.com/40660/ { "au ...

  10. Applet 数字签名技术完全攻略

      这里说声对不起大家.毕竟2几年前,我想写这篇文章,但因为他才懒得一直没有写.同时也给自己的东西好.前些日子我老大让我又搞这个东西发现我曾经的资料没留,又凭着自己印象从新来过.但发现网上写的东西真的 ...