尝试理解self关键字以及如何在函数链中使用它 - LUA

我知道如何在从头创建新表时堆叠函数,比如:

Test:newNumber(5):add5():add5() --创建Number{},Num=5,添加到self.num

但是当我尝试将以前存在的表传递进去时,我遇到了问题:

function EnemyBase:isStandingOver( Object )
    local o = Object
    for k,v in pairs(Creature_Bases) do
        if (o.x and o.y are over v.x and v.y) then
            setmetatable( Creature_Bases[k] , self )
            self.__index = self
            return Creature_Bases[k]
        end
    end
end

function EnemyBase:changeSprite()
    self.Sprite = self.SpriteTest
end

function ManageEnemies()
    for k,v in pairs(Enemies) do
        if EnemyBase:isStandingOver( Enemies[k] ) ~= nil then
            EnemyBase:isStandingOver( Enemies[k] ):changeSprite()
        end
    end
end

我知道我需要在某个时候创建一个元方法表,将__index指向self,但我不知道什么时候。

原文链接 https://stackoverflow.com/questions/69517809

点赞
stackoverflow用户2858170
stackoverflow用户2858170

让我们首先明白什么是 self

function a:b() endfunction a.b(self) end语法糖

像那样定义的函数有一个参数 self

函数调用 a:b()a:b(a) 的语法糖。

像那样调用的函数始终将 a 作为其第一个参数,在函数内部结束时成为参数 self

因此,如果您已经像那样定义了函数,则可以通过 self 很简单地访问表 a 中的元素,而无需显式使用引用 a。 如果您想在 Lua 中进行 OOP,则这非常方便。

然后我们需要了解 __index 元方法 是什么。

__index:索引访问操作 table\[key\]。 当 table 不是表或 key 不在 table 中存在时发生此事件。 元值在 table 的元表中查找。

此事件的元值可以是函数,表或具有 __index 元值的任何值。 如果是函数,则将使用 table 和 key 作为参数调用它,并将调用的结果(调整为一个值)作为操作的结果。否则,最终结果是使用 key 对此元值进行索引的结果。此索引是常规索引,而不是原始索引,因此可能会触发另一个 __index 元值。

让我们在一个简单的构造函数中使用这两个元素:

MyClass = {}
function MyClass:New(name)
  local instance = setmetatable({}, self)
  self.__index = self
  instance.name = name
  return instance
end

function MyClass:SayName()
  print("my name is " .. self.name)
end

如果我们现在这样做:

local myFirstInstance = MyClass:New("John")
local mySecondInstance = MyClass:New("Bob")

myFirstInstance:SayName()
mySecondInstance:SayName()

会发生什么?

我们知道 MyClass:New() 等同于 MyClass.New(MyClass)。因此,在我们的构造函数中,self 指的是 MyClass

local instance = setmetatable({}, self) 创建一个新表并将其设置为其元表的 self,即 MyClass

self.__index = selfMyClass 作为其自身的 __index 元值。

name 存储在每个实例中,并返回实例。

现在,如果您调用 myFirstInstance:SayName(),Lua 将查找 myFirstIntance["SayName"]。它找不到任何东西。因此,它将检查表 myFirstInstance 是否具有元表,并且如果存在元值,则检查是否存在 __index 元值。有。getmetatable(myFirstInstance).__index 是 MyClass,因此它现在实际上将调用 MyClass.SayName(myFirstInstance)。因此,最终,两个实例都将打印自己的名称,即使它们甚至没有实现 SayName 函数。MyClass.SayName 打印两个实例的名称,而不需要知道实例甚至名称。

2021-10-11 14:08:51