lua中的面向对象
2020-08-17 18:47
1401 查看
lua实现面向对象编程是基于元表
metatable,元方法__index来实现的。
lua中的语法糖
lua的table中可以定义函数,如下图:
local a = { x = 1, print = function(obj) print("x=" .. obj.x) end }
如上图,定义了一个名叫
a的table,可以通过调用
a.print(a)来打印table
a中的
xkey对应的value值。
像是
a.print(a)这种形式,在lua中可以简化为
a:print(),这是lua中的语法糖,使用
:而不是
.,lua会默认把 “调用者” 给传递进去。
元表 metatable
元表的表现行为类似于操作符重载,比如我们可以重载 __add,来计算两个 Lua 数组的并集;或者重载 __tostring,来定义转换为字符串的函数。
Lua 提供了两个处理元表的函数:
- setmetatable(table, metatable), 用于为一个 table 设置元表
- getmetatable(table),用于获取 table 的元表
比如:
local version = { major = 1, minor = 1, patch = 1 } version = setmetatable(version, { __tostring = function(t) return string.format("%d.%d.%d", t.major, t.minor, t.patch) end }) print(tostring(version)) -- 1.1.1
这段代码的作用就是重载了
version表的
tostring()方法,如果不重载的话,直接调用默认方法,那么打印结果是:
local version = { major = 1, minor = 1, patch = 1 } print(tostring(version)) -- table: 0x000647a8
元方法: __index
我们在 table 中查找一个元素时,首先会直接从 table 中查询,如果没有找到,就继续到元表的 __index 中查询。
local version = { major = 1, minor = 1} version = setmetatable(version, { __index = function(t, key) if key == "patch" then return 2 end end, __tostring = function(t) return string.format("%d.%d.%d", t.major, t.minor, t.patch) end }) print(tostring(version)) -- 1.1.2
这样当
t.patch取不到值时,就会去
__index中进行查找。
__index 不仅可以是一个函数,也可以是一个table。
local version = { major = 1, minor = 1} version = setmetatable(version, { __index = { patch=3 }, __tostring = function(t) return string.format("%d.%d.%d", t.major, t.minor, t.patch) end } ) print(tostring(version)) -- 1.1.3
上面的代码可以变换为如下形式:
local version = { major = 1, minor = 1} local mt = { __index = { patch=3 }, __tostring = function(t) return string.format("%d.%d.%d", t.major, t.minor, t.patch) end } version = setmetatable(version, mt) print(tostring(version)) -- 1.1.3
元方法:__call
使用
__call可以让 table 被调用。
local version = { major = 1, minor = 1, patch = 1 } local function print_version(t) print(string.format("%d.%d.%d", t.major, t.minor, t.patch)) end version = setmetatable(version, { __call = print_version } ) version() -- 1.1.1
面向对象
lua-resty-mysql 是OpenResty 官方的 MySQL 客户端,里面就使用元表模拟了类和类方法,它的使用方式如下所示:
local mysql = require "resty.mysql" -- 先引用 lua-resty 库 local db, err = mysql:new() -- 新建一个类的实例 db:set_timeout(1000) -- 调用类的方法
那么lua-resty-mysql的源码是如何实现的呢?
local _M = { _VERSION = '0.21' } -- 使用 table 模拟类 local mt = { __index = _M } -- mt 即 metatable 的缩写,__index 指向类自身 -- 类的构造函数 function _M.new(self) local sock, err = tcp() if not sock then return nil, err end return setmetatable({ sock = sock }, mt) -- 使用 table 和 metatable 模拟类的实例 end -- 类的成员函数 function _M.set_timeout(self, timeout) -- 使用 self 参数,获取要操作的类的实例 local sock = self.sock if not sock then return nil, "not initialized" end return sock:settimeout(timeout) end
上面的代码中,
-M这个table代表的就是mysql类,
_M.new(self)方法中返回一个
setmetatable({ sock = sock }, mt)就是返回一个类的对象,
socket这个属性就是这个对象的成员属性,而不是类的属性。
相关文章推荐
- lua面向对象实现(实例化对象、继承、多态、多继承、单例模式)
- LuaOO (Lua与C++交互的面向对象封装)
- Lua面向对象之一:简单例子
- Lua程序设计(二)面向对象概念介绍
- lua面向对象详解(1)
- LUA基础: TABLE, ARRAY, NAMESPACE, LUA的面向对象
- Lua面向对象实现
- Lua 面向对象
- Lua的面向对象实现方式
- lua面向对象实现的(记)
- lua面向对象学习
- LUA面向对象程序设计(一)类
- 笔记: Lua基础: Table, Array, Namespace, Lua的面向对象
- Lua面向对象
- Lua编程示例(二):面向对象、metatable对表进行扩展
- lua中的面向对象模拟,类,继承,多态
- lua面向对象
- 在 slua 中使用更新的面向对象方案
- Lua面向对象之二:类继承
- Lua学习之10:面向对象与继承