通过从函数返回的表来继承
2019-12-24 19:59:20
收藏:0
阅读:118
评论:1
有一个API提供的函数,让我们称之为 createBase,它返回一个表(对象)。我想向这个表中添加方法,但我不能只是 x = createBase(),然后 function x:foo(),因为我还有另一个类似 createBase 的函数,但它是 createExtended。为了更好地解释我现有的代码,可能更容易理解:
import api --我不知道你如何在vanilla Lua中实现这一点,我会使用os.loadAPI("api"),但那是特定于computercraft的,我认为
Extended = {}
function Extended:foo()
print("foo from extended")
end
function createExtended(params)
x = api.createBase(params)
Extended.__index = x
return Extended --这显然是错误的:你不能返回一个类并希望它成为一个对象
end
当然,这不起作用:但我也不知道我如何使它起作用。假设 createBase 返回的表中有一个名为 bar 的函数,它只打印 bar from base。使用此测试代码,将给出以下输出:
e = createExtended()
e.foo() --打印 "foo from extended"
e.bar() --nil,因此出错
除了在 createExtended 中定义 function x.bar(),我如何使这成为可能?
提前致谢。
点赞
评论区的留言会收到邮件通知哦~
推荐文章
- Lua 虚拟机加密load(string.dump(function)) 后执行失败问题如何解决
- 我想创建一个 Nginx 规则,禁止访问
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?

最简单的方法是直接将该方法附加到对象上,而不是使用元表。
local function extend(super_instance) super_instance.newMethod = newMethod return super_instance end local function createExtended(...) return extend(createSuper(...)) end这种方法可以正常工作,除非您的超类使用了
__newindex(例如,防止您对未知属性/方法进行写入),或者使用pairs或next遍历键,因为它现在具有额外的键。如果由于某种原因您不能修改对象,则必须对其进行"包装"。
您可以创建一个新实例,将其中所有的方法、属性和运算符“代理”到另一个实例上,除此之外还添加了额外的字段和方法。
local function extend(super_instance) local extended_instance = {newMethod = newMethod} -- 还可以根据需要添加 `__add`、`__mul` 等 return setmetatable(extended_instance, {__index = super_instance, __newindex = super_instance}) end local function createExtended(...) return extend(createSuper(...)) end这对于简单的类来说是可以工作的,但不适用于所有的场景:
像
pairs和next这样的表迭代器不会找到原始表的键,因为它们实际上不存在。如果超类检查给定的对象的元表(或者如果超类实际上是一个用户数据),那么它也无法正常工作,因为您会找到扩展元表。但是,许多纯 Lua 类不会执行这些操作,因此这仍然是一个相当简单的方法,可能适合您的情况。
您还可以像 Go 一样做一些类似的事情;而不是有一种方法来“扩展”类,您只需将该类嵌入为一个字段,并提供一种直接调用包装类上的方法的方便方式,这些方法只是直接调用“扩展”类上的方法。
由于 Lua 中“方法”的工作方式略微复杂,您无法确定某个属性是一个函数属性还是一个实际的方法。下面的代码假定所有的属性都是
type(v) == "function"的方法,这通常是正确的,但对于您的特定情况可能并不完全正确。在最坏的情况下,您只需手动维护您要代理的方法/属性列表,但这取决于您需要代理的类数量以及它们拥有的属性数量,这可能会变得不易管理。
local function extend(super_instance) return setmetatable({ newMethod = newMethod, -- 也可以通过更复杂的 __index 提供 }, { __index = function(self, k) -- 将除`newMethod`以外的所有内容代理到`super_instance`。 local super_field = super_instance[k] if type(super_field) == "function" then -- 假设访问是获取方法,因为它是一个函数。 return function(self2, ...) assert(self == self2) -- 假设它是像方法一样被调用的 return super_field(super_instance, ...) end end return super_field end, -- 如果需要,还可添加 __newindex 和 __add 等。 }) end local function createExtended(...) return extend(createSuper(...)) end