如何更改 table 的元 table 但在 Lua 中继承它自己的方法
How to change a table's metatable but inherit it's own methods in Lua
在Lua中,我们是这样进行面向对象编程的:
MyClass = {}
function MyClass:new()
local obj = {}
setmetatable(obj, self)
self.__index = self
obj.hello = "hello world"
return obj
end
function MyClass:sayHi()
print(self.hello)
end
function main()
local obj = MyClass:new()
obj:sayHi()
end
当处理更多 compelx 的东西时,通常我利用 Lua 的元方法来代理函数调用并用它做任何我需要的事情,比如参数解析等,通过添加这个:
MyClassMeta = {}
function MyClassMeta.__index(obj, funcName)
return function (self, ...)
//do some stuff
print("you called " .. funcName .. " with args", ...)
end
end
并更改行:
setmetatable(obj, self)
至:
setmetatable(obj, MyClassMeta)
我用 MyClass
实例调用的每个函数都将执行在 MyClassMeta.__index
元方法中实现的代码。
我现在要做的是继承MyClass
已有的方法,只对不属于MyClass
.
的函数执行MyClassMeta.__index
在上面的示例中,代码将始终执行MyClassMeta.__index
元方法,即使在调用MyClass:sayHi()
:
时也是如此
function main()
local obj = MyClass:new()
obj:sayHi("hello")
end
you called sayHi with args hello
当您将 __index
设置为 table 时,它将在 table 和 return 上查找属性(如果它们不存在于实例中)。由于 sayHi
存在于 MyClass
table 上,因此被使用。
self.__index = self
当您将 __index
设置为一个函数时,它可以 return 任何实例上不存在的属性。您可以检查密钥是否存在于 MyClass table 和 return 上,如果不存在则执行其他操作:
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)
有 Egor 评论的版本
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)
创建对象时,这会将新对象的元table的__index
设置为MyClass
,而MyClass的元table的索引是后备。因此,如果 属性 不在您的对象 或 MyClass 上的 上,它将使用回退。
在Lua中,我们是这样进行面向对象编程的:
MyClass = {}
function MyClass:new()
local obj = {}
setmetatable(obj, self)
self.__index = self
obj.hello = "hello world"
return obj
end
function MyClass:sayHi()
print(self.hello)
end
function main()
local obj = MyClass:new()
obj:sayHi()
end
当处理更多 compelx 的东西时,通常我利用 Lua 的元方法来代理函数调用并用它做任何我需要的事情,比如参数解析等,通过添加这个:
MyClassMeta = {}
function MyClassMeta.__index(obj, funcName)
return function (self, ...)
//do some stuff
print("you called " .. funcName .. " with args", ...)
end
end
并更改行:
setmetatable(obj, self)
至:
setmetatable(obj, MyClassMeta)
我用 MyClass
实例调用的每个函数都将执行在 MyClassMeta.__index
元方法中实现的代码。
我现在要做的是继承MyClass
已有的方法,只对不属于MyClass
.
MyClassMeta.__index
在上面的示例中,代码将始终执行MyClassMeta.__index
元方法,即使在调用MyClass:sayHi()
:
function main()
local obj = MyClass:new()
obj:sayHi("hello")
end
you called sayHi with args hello
当您将 __index
设置为 table 时,它将在 table 和 return 上查找属性(如果它们不存在于实例中)。由于 sayHi
存在于 MyClass
table 上,因此被使用。
self.__index = self
当您将 __index
设置为一个函数时,它可以 return 任何实例上不存在的属性。您可以检查密钥是否存在于 MyClass table 和 return 上,如果不存在则执行其他操作:
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)
有 Egor 评论的版本
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)
创建对象时,这会将新对象的元table的__index
设置为MyClass
,而MyClass的元table的索引是后备。因此,如果 属性 不在您的对象 或 MyClass 上的 上,它将使用回退。