Когда вы устанавливаете __index
для таблицы, она будет искать свойства в этой таблице и возвращать их, если они не существуют в экземпляре. Поскольку sayHi
существует в таблице MyClass
, она используется.
self.__index = self
Когда вы устанавливаете __index
для функции, она может возвращать что угодно для свойств, которые не существуют в экземпляре. Вы можете проверить, существует ли ключ в таблице MyClass и вернуть его, а затем сделать что-то еще, если его нет:
MyClass = {}
MyMetatable = {
__index = function(obj, key)
if MyClass[key] ~= nil then return MyClass[key] end
return function(self, ...)
print("you called "..tostring(key))
print(" self.hello is '"..tostring(self.hello).."'")
print(" with args", ...)
end
end
}
function MyClass:new()
local obj = {}
setmetatable(obj, MyMetatable)
obj.hello = "hello world"
return obj
end
function MyClass:sayHi()
print(self.hello)
end
function main()
local obj = MyClass:new()
obj:sayHi()
end
local obj = MyClass:new()
obj:sayHi("hello")
obj:somethingElse(1, 2, 3)
Версия с комментариями Егора
MyClass = {}
setmetatable(MyClass, {
-- if it's not found on MyClass, return a function
__index = function(self, funcName)
return function(self, ...)
print("you called "..funcName.." with args", ...)
end
end
})
function MyClass:new()
local obj = {}
-- if it's not found on obj, try self (MyClass)
setmetatable(obj, { __index = self })
obj.hello = "hello world"
return obj
end
function MyClass:sayHi()
print(self.hello)
end
local obj = MyClass:new()
obj:sayHi()
obj:somethingElse(1, 2, 3)
При создании объекта это устанавливает __index
метатаблицы нового объекта равным MyClass
, а индекс метатаблицы MyClass для функции, которая является резервной. Поэтому, если свойство не находится в вашем объекте или в MyClass, оно будет использовать запасной вариант.