lua的元表有什么好玩的

Posted 宋萌萌萌

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了lua的元表有什么好玩的相关的知识,希望对你有一定的参考价值。

很久之前咱们聊过  —— 表,我们知道元表可以看做lua中的类,但本质上它是一个普通的表,里面存了一些key-value。最常见的key和value就是 function name function pointer ,函数名是个字符串类型,函数指针则指向函数的存放地址。


既然元表是个普通的表,也就是说看着不爽的地方可以任人修改喽~

比如,因为sdk实现的一些特性,我们嫌弃window设置 viewAppear 回调总是最后一次设置的那个生效,那么该怎样重写这个 viewAppear 方法使得所有设置的回调都生效呢?

window 对lua来说是个userdata类型的数据,这个userdata有个元表,我们可以通过 getmetatable() 方法来获取它。
local mt = getmetatable(window)

然后,我们修改元表里viewAppear对应的函数

--- 首先我们在元表中塞个表,来存放修改后的viewAppear函数的参数mt.viewAppearFuncTable = {}
--- 获取viewAppear方法的指针local oriViewAppear = mt["viewAppear"]
--- 将viewAppear指向我们自定义的方法mt["viewAppear"] = function(_, func)    -- 对func做个校验,然后保存到viewAppearFuncTable中    if type(func) == "function" then        --- 因为viewAppearFuncTable是给元表添加的,所以window也可以访问到该字段        table.insert(window.viewAppearFuncTable, func)    endend--- 以上代码就完成了对viewAppear的重定义
--- 然后,设置真正的viewAppear回调,并对事件进行分发oriAppear(window, function()    for _, f in ipairs(window.viewAppearFuncTable) do if type(f) == "function" then f() end    endend)

oriAppear(window, function() end

这个方法可能会让大家觉得很奇怪,因为通常我们使用window:viewAppear(func)时只有一个参数。为什么单独调用方法时会多一个参数呢?

实际上当我们通过一个函数指针调用函数时,相当于点调用,点调用时需要明确的将被操作对象作为第一个参数,所以这里多了一个参数window,因为我们想让window调用它原来的那个viewAppear方法。


以上的操作思路就是替换原方法实现,将设置的callback保存在一个可访问的表中。再通过原方法指针调用原方法,并在设置的回调中对事件进行分发,由此将1v1的事件通知,调整成了1vN

当然啦,还可以用类似的套路修改 onDestroy viewDisappear 等方法。



上面涉及到一个小的知识点,就是我给 window的元表新增了一个表,并把lua设置的callback参数保存到了这个表里。也就是说window的元表实际上只有一个,只要能访问到window就能拿到window的元表。就好像在原生你说只要给我一个对象,我就能拿到这个对象的所属类是一样的道理。
同理在MLN中,所有的view(通过View()方法创建的对象)拥有同一张元表,所有的ImageView拥有另一张元表,等等等~

总结:
  1.  MLN提供的对象以及创建的对象,都拥有元表

  2. 元表是一个普通的lua表

  3. 元表中通过k-v形式保存这个类拥有的方法

  4. 元表的内容为所有对象公用,任意对象可以直接访问(不会线程问题哈,这个以后再解释)

  5. 你可以对元表进行各种魔改(有一点要注意:不要把原来的东西弄丢)


以上是关于lua的元表有什么好玩的的主要内容,如果未能解决你的问题,请参考以下文章

Lua元表和元方法DaemonCoder

lua的元表与元方法

lua中的元表---metatable

lua中的元表---metatable

Lua中的元表(metatable)元方法(metamethod)详解

Lua中的元表与元方法