Lua下通过元表模拟OOP编程,继承多态

Lua本身是没有以明确的定义来支持OOP编程的,但是我们却可以通过Lua内核提供的一些特性来间接实现简单的面向对象的编程。

通过Lua中的 table结构  metatable 以及函数可以配合实现OOP,以及继承。这些说白了都是一种伪实现,不建议在Lua下使用多重继承 。

在LUA中你想要 强制实现OOP 你必须需要懂一下几个关键词!!

什么是语法糖?

语法糖即糖衣语法,C/C++升级过程中的面向对象 整体就是一种语法糖 ,是由英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会。

比如char str[100] ;我访问第一个 字符 我是不是可以这样    str[1]   *(str+1) 简化了 代码编写 使粘合度 更高 就是一种语法糖。用过c#的人可以发现,C#的语法糖做到了极致。

什么是table?

Lua中的结构只有table,他是基于 HashMap  与索引数组与 一身,能存放任意类型数据,包括函数 何以其他表  这也就是  我们模拟集成的奠定了基础。

什么是metable?

local tb={["a"=1]}  这么一段代码 ,假如 我print(tb.b) 那么会提示找不到b,

这个时候叫做元表的metable 就起作用了,这会触发lua的 搜索机制,就去从metatable 中 搜索 b  这一点是不是和 javascript 的  prototype 类型呢?

这也就是我们实现继承的基础

 table中的__index是做什么用的?

他是一个函数,这个函数告诉Lua解释器  当在一个table中找不到  相对应元素的时候 如何从 metable 中搜索元素。

--语法糖 两种等价操作
--Class.__index=function(key)return Class[key] end
--设定外部搜寻对象
Class.__index=Class 

--函数调用的语法糖等价操作
  local a={}
--lua中的函数默认都是有self传递进去的  语法糖会自动给我们传递 self
--也就是说通过.调用table的函数如果函数内部引用self 需要我们在调用的时候手动传递对象a进去
--但是通过:调用的话 Lua解释器 默认在每个函数调用给我们 吧 a给传递进去了  在函数内部引用 就叫做self
  a:b()== a.b(a)  

function SubClass:test()
    print("test is child ")
end
我们可以直接
SubClass.test(SubClass)
也可以 直接调用
SubClass:test()

实现OOP

--模拟实现OOP
--通过table定义类模型
Class={}
--语法糖 实际上被转换为
--Class.__index=function(key)return Class[key] end
--设定外部搜寻对象
Class.__index=Class
function Class:new(x)      --语法糖而已
   print('模拟构造函数!')
   local temObj={}
   temObj.x=x
   --设置meta object
   setmetatable(temObj,self)
   return  temObj
end

function Class:ShowData()
    print("self.x:",self.x)
end

function Class:delete()
   self.x=nil
   print('模拟析构函数!')
end

local clsObj=Class:new(1)
--隐式传递clsObj作为 self 参数
clsObj:ShowData()
--显示传参作为self参数
clsObj.ShowData(clsObj)
clsObj:delete()

结果如下

LUA模拟实现继承

--模拟实现OOP
--通过table定义类模型
Class={}
--语法糖 实际上被转换为
--Class.__index=function(key)return Class[key] end
--设定外部搜寻对象
Class.__index=Class
function Class:new()
   print('模拟构造函数!')
   local temObj={}
   --设置meta object
   setmetatable(temObj,self)
   return  temObj
end

function Class:parent()
    print("parent is ",type(self))
end

function Class:delete()
   print('模拟析构函数!')
end

--从基类创建对象
SubClass=Class:new()
--设置__index搜索 范围
SubClass.__index=SubClass
--派生构造函数
function SubClass:new()
  local obj={}
--设置派生metable为self 就是 SubClass
  setmetatable(obj,self)
--返回对象
  return obj
end
---派生对象方法
function SubClass:child()
    print("child is ",type(self))
end

--创建一个派生对象
local  obj=SubClass:new()
--通过语法糖调用不同方法
obj:child()
obj:parent()
--语法糖等价于
obj.child(obj)
obj.parent(obj)

模拟实现多态

既然继承我们都实现了 多态我们只需要在不同的类型中添加不同的定语法糖函数义即可

--模拟实现多态
Class={}
--语法糖 实际上被转换为
--Class.__index=function(key)return Class[key] end
--设定外部搜寻对象
Class.__index=Class
function Class:new()
   print('基类模拟构造函数!')
   local temObj={}
   --设置meta object
   setmetatable(temObj,self)
   return  temObj
end
--
function Class:test()
    print("test is parent")
end

--从基类创建对象
SubClass=Class:new()
--设置__index搜索 范围
SubClass.__index=SubClass
--派生构造函数
function SubClass:new()
  local obj={}
--设置派生metable为self 就是 SubClass
  setmetatable(obj,self)
--返回对象
  return obj
end
--override方法
function SubClass:test()
    print("test is child ")
end
--创建一个派生对象
local  objChild=SubClass:new()
--创建一个基类对象
local parentObj=Class:new()
parentObj:test();
objChild:test();

参考资料

http://blog.csdn.net/ym012/article/details/7206968

http://www.xuebuyuan.com/1613223.html

http://blog.csdn.net/xocoder/article/details/9028347

http://www.cnblogs.com/zhiranok/archive/2012/02/07/lua_object_skill.html

时间: 2024-10-17 04:30:37

Lua下通过元表模拟OOP编程,继承多态的相关文章

【游戏开发】在Lua中实现面向对象特性——模拟类、继承、多态

一.简介 Lua是一门非常强大.非常灵活的脚本语言,自它从发明以来,无数的游戏使用了Lua作为开发语言.但是作为一款脚本语言,Lua也有着自己的不足,那就是它本身并没有提供面向对象的特性,而游戏开发是一项庞大复杂的工程,如果没有面向对象功能势必会为开发带来一定的不便.不过幸好Lua中有table这样强大的数据结构,利用它再结合元表(metatable),我们便可以很方便地在Lua中模拟出类.继承和多态等面向对象编程具有的特性. 二.前提知识 按照惯例,我们还是先来熟悉一下必要的前提知识,以便方便

LUA OOP编程实现方法

lua原生不支持OOP特性 确实如此, 同时可以采用其它lua代码的方式实现OOP的特性. OOP四大特性 抽象 封装 继承 多态 http://www.cnblogs.com/xiaosongluffy/p/5072501.html 四大基本特性: 抽象:提取现实世界中某事物的关键特性,为该事物构建模型的过程.对同一事物在不同的需求下,需要提取的特性可能不一样.得到的抽象模型中一般包含:属性(数据)和操作(行为).这个抽象模型我们称之为类.对类进行实例化得到对象. 封装:封装可以使类具有独立性

javascript oop编程 — 实现继承的三种形式

javascript  oop编程  - 实现继承的三种形式[1] (1)模拟类的方式, 我们都知道js是原型继承机制,不存在class和instance分离的这种方式 假设,我们有两个类 function  Animal(){ this.name = "animal"; this.eat = function(){ consle.log("eating"); } } function Cat(){ this.say = function(){ console.lo

C++ Primer 学习笔记_69_面向对象编程 --继承情况下的类作用域

面向对象编程 --继承情况下的类作用域 引言: 在继承情况下,派生类的作用域嵌套在基类作用域中:如果不能在派生类作用域中确定名字,就在外围基类作用域中查找该名字的定义. 正是这种类作用域的层次嵌套使我们能够直接访问基类的成员,就好像这些成员是派生类成员一样: Bulk_item bulk; cout << bulk.book() << endl; 名字book的使用将这样确定[先派生->后基类]: 1)bulk是Bulk_item类对象,在Bulk_item类中查找,找不到名

C++ Primer 学习笔记_69_面向对象编程 -继承景况下的类作用域

面向对象编程 --继承情况下的类作用域 引言: 在继承情况下,派生类的作用域嵌套在基类作用域中:如果不能在派生类作用域中确定名字,就在外围基类作用域中查找该名字的定义. 正是这种类作用域的层次嵌套使我们能够直接访问基类的成员,就好像这些成员是派生类成员一样: Bulk_item bulk; cout << bulk.book() << endl; 名字book的使用将这样确定[先派生->后基类]: 1)bulk是Bulk_item类对象,在Bulk_item类中查找,找不到名

Lua中的元表与元方法

前言 元表对应的英文是metatable,元方法是metamethod.我们都知道,在C++中,两个类是无法直接相加的,但是,如果你重载了“+”符号,就可以进行类的加法运算.在Lua中也有这个道理,两个table类型的变量,你是无法直接进行“+”操作的,如果你定义了一个指定的函数,就可以进行了.那这篇博文就是主要讲的如何定义这个指定的函数,这个指定的函数是什么?希望对学习Lua的朋友有帮助. Lua是怎么做的? 通常,Lua中的每个值都有一套预定义的操作集合,比如数字是可以相加的,字符串是可以连

Lua语言基础汇总(8) -- Lua中的元表与元方法

前言 元表对应的英文是metatable,元方法是metamethod.我们都知道,在C++中,两个类是无法直接相加的,但是,如果你重载了“+”符号,就可以进行类的加法运算.在Lua中也有这个道理,两个table类型的变量,你是无法直接进行“+”操作的,如果你定义了一个指定的函数,就可以进行了.那本文就是主要讲的是如何定义这个指定的函数,这个指定的函数是什么?希望对学习Lua的朋友有帮助. Lua是怎么做的? 通常,Lua中的每个值都有一套预定义的操作集合,比如数字是可以相加的,字符串是可以连接

[转]Lua中的元表与元方法

前言 元表对应的英文是metatable,元方法是metamethod.我们都知道,在C++中,两个类是无法直接相加的,但是,如果你重载了“+”符号,就可以进行类的加法运算.在Lua中也有这个道理,两个table类型的变量,你是无法直接进行“+”操作的,如果你定义了一个指定的函数,就可以进行了.那这篇博文就是主要讲的如果定义这个指定的函数,这个指定的函数时什么?希望对学习Lua的朋友有帮助. Lua是怎么做的? 通常,Lua中的每个值都有一套预定义的操作集合,比如数字是可以相加的,字符串是可以连

【转】Lua coroutine 不一样的多线程编程思路

Lua coroutine 不一样的多线程编程思路 Sunday, Apr 26th, 2009 by Tim | Tags: coroutine, Lua 上周末开始看<Lua程序设计>第二版,目前体会到其中比较有趣的有两点,一是强大的table数据结构,另外就是coroutine.也许Lua 中的coroutine是一种很好的设计模式,但我初步的体会还是没想到其他语言和场合能非常适合用到coroutine的场景. 一.简介 协同程序与线程差不多,也就是一条执行序列,拥有自己独立的栈,局部变