[Lua]Lua的面向对象程序设计

Lua中的表不仅在某种意义上是一种对象。像对象一样,表也有状态(成员变量);也有与对象的值独立的本性,特别是拥有两个不同值的对象(table)代表两个不同的对象;一个对象在不同的时候也可以有不同的值,但他始终是一个对象;与对象类似,表的生命周期与其由什么创建、在哪创建没有关系。

local Account = {balance = 0}
function Account.withdraw(v)
    Account.balance = Account.balance - v
end
--调用方法如下:
Account.withdraw(100.00)
local a = Account
Account = nil
a.withdraw(100.00)   -- ERROR!--这种行为违背了前面的对象应该有独立的生命周期的原则。

一个灵活的方法是:定义方法的时候带上一个额外的参数,来表示方法作用的对象。这个参数经常为self或者this:

function Account.withdraw(self, v)
    self.balance = self.balance - v
end

self参数的使用是很多面向对象语言的要点。大多数OO语言将这种机制隐藏起来,这样程序员不必声明这个参数(虽然仍然可以在方法内使用这个参数)。Lua也提供了通过使用冒号操作符来隐藏这个参数的声明。我们可以重写上面的代码:

function Account:deposit(v)
    self.balance = self.balance + v
end
--调用方法如下:
a:withdraw(100.00)

冒号的效果相当于在函数定义和函数调用的时候,增加一个额外的隐藏参数。这种方式只是提供了一种方便的语法,实际上并没有什么新的内容。

一些面向对象的语言中提供了类的概念,作为创建对象的模板。在这些语言里,对象是类的实例。Lua不存在类的概念,每个对象定义他自己的行为并拥有自己的形状(shape)。然而,依据基于原型(prototype)的语言比如Self和NewtonScript,在Lua中仿效类的概念并不难。在这些语言中,对象没有类。相反,每个对象都有一个prototype(原型),当调用不属于对象的某些操作时,会最先会到prototype中查找这些操作。在这类语言中实现类(class)的机制,我们创建一个对象,作为其它对象的原型即可(原型对象为类,其它对象为类的instance)。类与prototype的工作机制相同,都是定义了特定对象的行为。

在Lua中,很容易实现prototypes.更明确的来说,如果我们有两个对象a和b,我们想让b作为a的prototype只需要:setmetatable(a, {__index = b})

local Account = {balance = 0}
function Account:new(o)
    o = o or {}
    setmetatable(o,{__index = self})
    return o
end
function Account:deposit (v)
    self.balance = self.balance + v
    print(self.balance)
end
a = Account:new{balance = 0}
a:deposit(100.00) --输出 100

继承

local Account = {balance = 0}
function Account:new(o)
    o = o or {}
    setmetatable(o,{__index = self})
    return o
end
function Account:deposit(v)
    self.balance = self.balance + v
    print("Account:deposit",self.balance)
end
function Account:withdraw(v)
    if v > self.balance then
        error"insufficient funds"
    end
    self.balance = self.balance - v
    print("Account:withdraw",self.balance)
end

local SpecialAccount = Account:new()
function SpecialAccount:withdraw(v)
    if v - self.balance >= self:getLimit() then
        error"insufficient funds"
    end
    self.balance = self.balance - v
    print("SpecialAccount:withdraw",self.balance)
end
function SpecialAccount:getLimit()
    print("SpecialAccount:getLimit",self.limit or 0)
    return self.limit or 0
end

local s = SpecialAccount:new{limit=1000.00}
function s:getLimit ()
    print("s:getLimit",self.balance * 0.10)
    return self.balance * 0.10
end

s:deposit(100.00)
s:withdraw(10.00)
--输出
--Account:deposit 100
--s:getLimit  10
--SpecialAccount:withdraw 90

s的表结构

多重继承

在Lua中多重继承的实现的关键在于:将函数用作__index。记住,当一个表的metatable存在一个__index函数时,如果Lua调用一个原始表中不存在的函数,Lua将调用这个__index指定的函数。这样可以用__index实现在多个父类中查找子类不存在的域。

多重继承意味着一个类拥有多个父类,所以,我们不能用创建一个类的方法去创建子类。取而代之的是,我们定义一个特殊的函数createClass来完成这个功能,将被创建的新类的父类作为这个函数的参数。这个函数创建一个表来表示新类,并且将它的metatable设定为一个可以实现多继承的__index metamethod。尽管是多重继承,每一个实例依然属于一个在其中能找得到它需要的方法的单独的类。所以,这种类和父类之间的关系与传统的类与实例的关系是有区别的。特别是,一个类不能同时是其实例的metatable又是自己的metatable。

local function search(k, plist)
    for i=1,table.getn(plist) do
        local v = plist[i][k]
        if v then return v end
    end
end
function createClass(...)
    local c = {} -- new class
    setmetatable(c,{__index = function(t, k) return search(k,arg) end})
    function c:new (o)
        o = o or {}
        setmetatable(o,{__index = c})
        return o
    end
    return c
end

local Named = {}
function Named:getname()
    return self.name
end
function Named:setname(n)
    self.name = n
end

local NamedAccount = createClass(Account, Named)
local ssaccount = NamedAccount:new{name = "Paul"}
print(ssaccount:getname())    --> Paul

私有性

用一个table表来保存数据,用另一个表table来保存函数。

其他相关内容可参看,《Lua基础(二)——表》,《Lua表相关元方法》,《Lua进阶(一)——函数闭包、元表

时间: 2024-08-02 20:19:42

[Lua]Lua的面向对象程序设计的相关文章

lua中的面向对象编程

简单说说Lua中的面向对象 Lua中的table就是一种对象,看以下一段简单的代码: 上述代码会输出tb1 ~= tb2.说明两个具有相同值得对象是两个不同的对象,同时在Lua中table是引用类型的.我在<Lua中的模块与包>中也总结了,我们是基于table来实现的模块,在table中可以定义函数,也就是说,每个table对象都可以拥有其自己的操作.看一段代码: 上面的代码创建了一个新函数,并将该函数存入Account对象的withDraw字段中,然后我们就可以调用该函数了.不过,在函数中使

Cocos2d-x 脚本语言Lua中的面向对象

Cocos2d-x 脚本语言Lua中的面向对象 面向对象不是针对某一门语言,而是一种思想.在面向过程的语言也能够使用面向对象的思想来进行编程. 在Lua中,并没有面向对象的概念存在,没有类的定义和子类的定义.但相同在Lua中能够利用面向对象的思想来实现面向对象的类继承. 一.复制表的方式面向对象 --Lua中的面向对象 --[[ 复制表方式面向对象 參数为一张表.通过遍历这张表取值,赋给一张空表,最后返回新建的表.来达到克隆表 ]] function clone(tab) local ins =

Lua程序转载 - 面向对象的实现探讨

> 转载出处:http://blog.csdn.net/xenyinzen/article/details/3536708 元表概念     Lua中,面向对向是用元表这种机制来实现的.首先,一般来说,一个表和它的元表是不同的个体(不属于同一个表),在创建新的table时,不会自动创建元表.但是,任何表都可以有元表(这种能力是存在的). e.g.t = {}print(getmetatable(t))   --> nilt1 = {}setmetatable(t, t1)assert(getm

Lua语言基础汇总(12)-- Lua中的面向对象编程

简单说说Lua中的面向对象 Lua中的table就是一种对象,看以下一段简单的代码: 1 2 3 4 5 6 7 8 9 10 11 12 local tb1 = {a = 1, b = 2} local tb2 = {a = 1, b = 2} local tb3 = tb1   if tb1 == tb2 then      print("tb1 == tb2") else      print("tb1 ~= tb2") end   tb3.a = 3 pri

[转]Lua中的面向对象实现方法

面向对象不是针对某一门语言,而是一种思想,在面向过程的语言也可以使用面向对象的思想来进行编程.在Lua中,并没有面向对象的概念存在,没有类的定义和子类的定义,但同样在Lua中可以利用面向对象的思想来实现面向对象的类继承. 一.复制表的方式面向对象 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45

2062326 齐力锋 实验四《Java面向对象程序设计Android开发》实验报告

北京电子科技学院(BESTI) 实 验 报 告 课程: 程序设计与数据结构  班级: 1623  姓名: 齐力锋 学号: 20162326 成绩: 指导教师: 娄嘉鹏/王志强 实验日期: 2017年5月26日 实验密级:非密级 预习程度: 优良 实验时间: 2 Hours 仪器组次: 必修/选修: 必修 实验序号: 04 实验名称:Java面向对象程序设计Android开发 实验内容 1.Android Stuidio的安装测试: 参考<Java和Android开发学习指南(第二版)(EPUBI

PHP系列(四)PHP面向对象程序设计

php面向对象程序设计 面向对象的优势:可读性.可重用性.稳定性.维护性.可测试性 简单格式: [修饰符]class 类名{ [成员属性] [成员方法] } 完整格式: [修饰符]class 类名 [extends 父类]  [implements 接口 ] { [成员属性] [成员方法] } 成员方法格式: [修饰符] function 方法名(参数){ [方法体] [return返回值] } 修饰符:public  protected  private static  abstract  f

[.net 面向对象程序设计深入](4).NET MVC ——谈谈MVC的版本变迁及新版本6.0发展方向

[.net 面向对象程序设计深入](4).NET MVC ——谈谈MVC的版本变迁及新版本6.0发展方向 1.关于MVC 在本篇中不再详细介绍MVC的基础概念,这些东西百度要比我写的全面多了,MVC从1.0到5.0的时间也不短了,很多人只是按照范例去使用MVC的一些基础功能,并没有更加深入的了解MVC.在这一系列中,我主要介绍MVC的一些原理和使用技巧,以及MVC的发展方向. 先说说MVC,首先他是一种设计模式,如果你百度为什么GOF23种设计模式中没有MVC,答案很有意思,如下: “在他们看来

[.net 面向对象程序设计深入](1)UML——在Visual Studio 2013/2015中设计UML类图

[.net 面向对象程序设计深入](1)UML——在Visual Studio 2013/2015中设计UML类图 1.UML简介 Unified Modeling Language (UML)又称统一建模语言或标准建模语言. 简单说就是以图形方式表现模型,根据不同模型进行分类,在UML 2.0中有13种图,以下是他们的主要用途简介: 1.用例图:对系统的使用方式分类. 2.类图:显示类和它们的相互关系. 3.对象图:只显示对象及它们的相互关系. 4.活动图:显示人或对象的活动,其方式类似于流程

[.net 面向对象程序设计进阶] (5) Lamda表达式(二) 表达式树快速入门

[.net 面向对象程序设计进阶] (6) Lamda表达式(二) 表达式树快速入门 本节导读: 认识表达式树(Expression Tree),学习使用Lambda创建表达式树,解析表达式树. 学习表达式在程序设计中的优点:比如构造动态查询.动态构造表达式树完成未知对象属性访问,比反射的性能高出很多.我们可以说表达式树才是Lambda的精髓,是我们必须要熟练掌握并灵活运用的. 1.关于表达式树(Expression Tree) 表达式树以树形数据结构表示代码,其中每一个节点都是一种表达式,比如