如何设置一个元表来继承另一个元表,同时将userdata更改为另一种类型?

How do I set up a metatable to inherit from another metatable while at the same time changing the userdata to another type?

本文关键字:userdata 类型 另一种 继承 设置 何设置 一个 另一个      更新时间:2023-10-16

这是我想用Lua C API在c++中做的事情。

我试图找出一个好方法,使userdata从一个基本的userdata对象派生。

我希望能够这样做:

local item = me:GetCurrentItem()
print(item:GetPos())

代替:

local item = me:GetCurrentItem()
print(item:GetBaseObject():GetPos())

在这些例子中,me:GetCurrentItem()用一些函数返回userdata,但是它缺少item:GetBaseObject()返回的基函数。

我在《危机战争》SDK中绑定Lua是为了学习。SDK为基本实体提供了一个接口,它是一个结构体。IItem结构体(GetCurrentItem())是相同的。由于这些是结构体,我不能将它们强制转换为基结构体或调用其基函数。我必须使用IEntity *GetEntity()函数。

我尝试改变__index中的自我指针,但它导致局部变量"item"成为"实体",这有点明显,但我希望它在调用GetPos函数后恢复,这似乎不合逻辑。

对于这个问题,谁有好的解决方案?

最明显的解决方案是定义一个item:GetPos()函数来执行重定向。

function Item:GetPos()
  return self:GetBaseObject():GetPos()
end

其中Item是Item的元表。

这和修改元表一样有效,而且问题更少。

编辑:我也可以帮助你一点重复。

可以实现以下两个函数:

function delegate(klass, methodName, memberName)
  klass[methodName] = function(self, ...)
    local member = self[memberName]
    if type(member) == 'function' then member = self[memberName](self) end
    return member[methodName](member, ...)
  end
end

然后像这样使用:

delegate(Item, 'GetPos', 'GetBaseObject')

这一行将与上面的Item:GetPos 3行定义相同。

如果您需要多次重复此操作,您可以使用另一个函数进一步优化它:

function delegateMany(klass, methodNames, memberName)
  for _,methodName in ipairs(methodNames) do
    delegateMethod(klass, methodName, memberName)
  end
end

它应该允许你做:

deletageMany(Item, {'GetPost', 'SetPos', 'GetColor', 'SetColor'}, 'GetBaseObject')

我还没有测试过这些函数,所以要小心bug。他们应该工作与两个"得到的属性"(self:GetSomething()以及简单的访问self.something)。代码假设您总是使用':'来调用委托的方法,因此在需要时添加self