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

时间:2023-01-06 14:07:08

(本文转载)学习之用,侵权立删!

原文地址   http://blog.csdn.net/y_23k_bug/article/details/19965877?utm_source=tuicool&utm_medium=referral

lua面向对象实现:

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

lua中,面向对象是用元表这个机制来实现。

首先,一般来说一个表和它的元表是不同的个体(不属于同一个表),在创建新的表时,不会自动创建元表。

setmetatable函数:设置元表

setmetatable( 表1 , 表2 )  将表2挂接为表1的元表,并且返回经过挂接后的表1

__index字段:

元表中的__index字段,是一个非常强大的字段,它为回溯查询提供支持。而面向对象的实现基于回溯查询

当访问一个table中不存在的字段时,得到的结果为nil。但是如果这个表有元表的话,这个访问就会查找元表中的__index字段。如果没有__index字段没有赋值,那么访问结果为nil。否则,就由__index字段提供最终的结果。

__index可以赋值为一个函数,也可以是个表。是函数时,就会调用这个函数。是表的时候,就以相同的方式重新访问这个表。

注意:这里出现了三个表的个体,

我们直接操作的表,称之为表A,表A的元表称之为表B,表B的__index字段赋值的表,称之为表C

如果访问表A中的一个字段时,如果找不到,会去查看表A有没有元表B,如果有的话,就会查找B中的__index字段是否有赋值,如果赋值为表C,就会去表C中查找有没有想访问的那个字段,如果找到了,就返回那个字段,如果没有,就返回nil。

lua面向对象--对象创建

我们可以利用元表和元表__index字段来实现类对象的创建

在该类的构造函数中,定义一个新的表,然后把该类(表)设置为新定义的那个表的元表的__index字段,这样,当我们用实例的对象来调用该类的某个字段的时就会去该类中查找调用,这样就实现了对象的实例化。

例子

class.lua

local    class  = {}

function  class:new()

local self = {}     —创建新的表作为实例的对象

setmetatable( self , {__index = class})  —设置class为对象元表的__index

return self         —返回该新表

end

function class:func()

print(“class : func”)

end

return class

main.lua

local class = require(“class”)

s1 = class:new()   — 实例化对象s1

s1:func()               ——->class : func

lua面向对象--继承

lua实现继承和实现对象实例化是一样的,利用元表和元表的__index字段来实现。

例子

class1.lua

local class1 = {}

function class1:func1()

print(“class1 : func1”)

end

return class1

class2.lua

local class2 = {}

local class1 = require(“class1”)

function class2:func2()

print(“class2 : func2”)

end

function class2:new()

setmetatable(class2 , {__index = class1})  —设置class1为class2的元表的__index字段来实              现继承

— 实例对象

local self = {}

setmetatable(self , {__index = class2})

return self

end

return class2

main.lua

local class2 = require(“class2”)

local s1 = class2:new()

s1:func1()     ———>class1:func1

s1:func2()     ———>class2:func2

lua面向对象--多态

lua支持多态

例子:

class1.lua

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

function class1:new(x,y)

-- body

local self = {}

setmetatable(self,class1)

class1.__index = class1

self.x = x

self.y = y

return self

end

function class1:test()

print(self.x,self.y)

end

function class1:gto()

return 100

end

function class1:gio()

return self:gto()*2

end

return class1

class2.lua

local class2 ={}

local class2 = require("class1")

function class2:new(x,y)

setmetatable(class2, class1)

class1.__index = class2

local self = {}

setmetatable(self, class2)

class2.__index = class2

self.x = x

self.y = y

return self

end

function class2:gto()

return 50

end

return class2

main.lua

class1 = require(“class1”)

class2 = require(“class2”)

s1 = class1:new()

s2 = class2:new()

print(s1:gio())  ——->200

print(s2:gio())  ——>100

—s2对象调用基类class1的gio函数,函数内部调用class2的gto函数,实现了多态。

lua面向对象--多继承

lua中类的多继承实现也是利用的元表和元表的__index字段,不同于对象实例化和单一继承不同的是__index字段赋值的是一个函数而不是一个基类的表。

利用传入__index字段的函数来查找类中找不到的字段(函数中遍历该类继承的多个基类)

查找函数:

local function search(k,plist)

for i = 1,#plist do

local v = plist[i][k]

if v then return v end

end

end

—plist 为该类的基类的集合 ,k为要查找(调用继承的字段)的字段

实现继承函数:

local function createClass()

local parents = {class1,class2}

setmetatable(class3,{__index = function(t,k)

return search(k,parents)

end})

end

这样就可以实现多继承了。

例子:

class1.lua

local class1 = {}

function class1:func1()

print("class1--func1")

end

return class1

class2.lua

local class2 ={}

function class2:func2()

print("class2:func2")

end

return class2

class3.lua

local class3 = {}

local class1 = require("class1")

local class2 = require("class2")

local function search(k,plist)

for i = 1,#plist do

local v = plist[i][k]

if v then return v end

end

end

local function createClass()

local parents = {class1,class2}

setmetatable(class3,{__index = function(t,k)

return search(k,parents)

end})

end

function class3:func3()

print("class3:func3")

end

function class3:new()

local self = {}

createClass()

setmetatable(self,class3)

class3.__index = class3

return self

end

return class3

main.lua

local class3 = require("class3")

local s1 = class3:new()

s1:func1()    ————->class1:func1

s1:func2()    ————>class2:func2

s1:func3()    ————>class3:func3

lua面向对象--单例模式

lua的单例模式是利用一个全局表来实现的

例子:

CatManager = {}

CatManager_mt = {__index = CatManager}  —创建一个表做实例对象的元表,__index 设置为 这个单例类

function CatManager:new()

local self = {}

setmetatable( self , CatManager_mt)  —把全局的表CatManager设置为self(新创建表)的元表的__index字段

—每次获得单例时,创建一个self表(对象),该表继承全局表CatManager,每次修改全局表中的字段后,下次再次调用时,该字段都是已经修改过的

return self

end

function CatManager:func1()

print(“func1”)

end

main.lua

require(“CatManager”)

catManager = CatManager:new()

一次导入进来后  ,整个程序都可以用,实现了单例的效果

树欲静而风不止,子欲养而亲不待!

2016年12月19日17:23:18

Lua面向对象----类、继承、多继承、单例的实现的更多相关文章

  1. java双重检测或枚举类实现线程安全单例(懒汉模式)

    双重检测实现 /** * 懒汉模式->双重同步锁单例模式 */ public class SingletonExample5 { private SingletonExample5() { } ...

  2. Python中的私有属性私有方法、类属性类方法以及单例设计模式

    私有属性是对象不希望公开的属性,私有方法是对象不希望公开的方法.在定义私有属性和私有方法时,在属性或者方法前,加上__(两个下划线) 公有方法可以通过对象名直接调用,私有方法不能通过对象名直接调用,只 ...

  3. 类 __new__方法实现单例

    继承了单例的类,子类也是单例模式

  4. 【scala】类的定义和单例对象

    一.类的定义 Scala类的定义跟JAVA中类的定义基本是一样的. 示例 class ChecksumAccumulator{ var sum = 0;//Scala默认关键字为public priv ...

  5. spring mvc 的Controller类默认Scope是单例(singleton)的

    使用Spring MVC有一段时间了,之前一直使用Struts2,在struts2中action都是原型(prototype)的, 说是因为线程安全问题,对于Spring MVC中bean默认都是(s ...

  6. python面向对象学习(七)单例

    目录 1. 单例设计模式 单例设计模式的应用场景 2. __new__ 方法 3. Python 中的单例 只执行一次初始化工作 1. 单例设计模式 设计模式 设计模式 是 前人工作的总结和提炼,通常 ...

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

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

  8. Unity 游戏框架搭建 (十三) 无需继承的单例的模板

    之前的文章中介绍的Unity 游戏框架搭建 (二) 单例的模板和Unity 游戏框架搭建 (三) MonoBehaviour单例的模板有一些问题. 存在的问题: 只要继承了单例的模板就无法再继承其他的 ...

  9. (七)boost库之单例类

    (七)boost库之单例类 一.boost.serialzation的单件实现 单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例类的特殊类.通过单例模式可以保证系统中一个类只有一 ...

随机推荐

  1. Node.js连接Mysql,并把连接集成进Express中间件中

    引言 在node.js连接mysql的过程,我们通常有两种连接方法,普通连接和连接池. 这两种方法较为常见,当我们使用express框架时还会选择使用中间express-myconnection,可以 ...

  2. 1003. Emergency

    As an emergency rescue team leader of a city, you are given a special map of your country. The map s ...

  3. 查看mysql的注册表路径

    原文地址:http://www.cppblog.com/lanshengsheng/archive/2012/11/23/195592.html

  4. 修改LiteIDE 编辑窗口的主题

    用习惯了Visual Studio 再看其他编译器总是有点别扭,当然LiteIDE 也是能够自定义主题的,再次感叹作者的用心. 依次: 查看 -> 选项 -> LiteEditor 在编辑 ...

  5. JavaBean在DAO设计模式简介

    一.信息系统开发框架 客户层-------显示层-------业务层---------数据层---------数据库 1.客户层:客户层是client,简单的来说就是浏览器. 2.显示层:JSP/Se ...

  6. 详解C#的协变和逆变

    一.使用协变(Covariance)和逆变(Contravariance )能够实现数组之间.委托实例和方法之间.泛型委托实例之间.泛型接口的变量和泛型类型的对象之间.泛型接口的变量之间的隐式转换:使 ...

  7. Luogu 1080 【NOIP2012】国王游戏 (贪心,高精度)

    Luogu 1080 [NOIP2012]国王游戏 (贪心,高精度) Description 恰逢H国国庆,国王邀请n位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右手上面分别写下一个整数,国王自己 ...

  8. 20145325张梓靖 《网络对抗技术》 Web基础

    20145325张梓靖 <网络对抗技术> Web基础 实验内容 开启apahce,设计web前端HTML 设计web前端javascipt 设计web后端mysql 设计web后端php ...

  9. Python &lowbar;&lowbar;name&lowbar;&lowbar;变量

    原文: http://blog.csdn.net/u011511601/article/details/53504355 Python使用缩进对齐组织代码的执行,所有没有缩进的代码,都会在载入时自动执 ...

  10. func 的参数修饰

    1.0 在声明一个 Swift的方法的时候,我们一般不去指定参数前面的修饰符,而是直接声明参数: func incrementor(variable : Int) ->Int { } 这个方法接 ...