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