我可能遗漏了一些非常简单的东西,但是当在Lua中调用某个对象的方法时,有没有办法从self
变量中获取该对象的名称?
为了说明我的意思,这是一个有点人为的例子 - 一个简单的Stack实现:
Stack = {}
function Stack:new (...)
instance = {}
instance.elements = {...}
setmetatable(instance, self)
self.__index = self
return instance
end
function Stack:push (...)
for i,v in pairs({...}) do
table.insert(self.elements,v)
end
end
function Stack:pop ()
if #self.elements > 0 then
return table.remove(self.elements)
else
error("Cannot pop, Stack is empty")
end
end
my_stack = Stack:new(2,4)
my_stack:push("dog") -- my_stack.elements = {2,4,"dog"}
print(my_stack:pop()) -- "dog"
print(my_stack:pop()) -- "4"
print(my_stack:pop()) -- "2"
print(my_stack:pop()) -- error: "Cannot pop, Stack is empty"
是否可以使用self
错误消息中的Stack:pop
变量输出要调用的对象的名称?我希望错误消息说出" Cannot pop, Stack 'my_stack' is empty
"。
答案 0 :(得分:5)
有没有办法从自变量中获取该对象的名称?
Lua中的对象没有名称。只有引用具有名称,变量和表字段最终只是对象的引用。所以,如果你问如何获取引用的名称,显然你不能,因为可能有任意数量的引用具有不同的名称,哪一个“self.getName()”返回?
您可以为每个对象提供唯一的标识符,例如在构建时。然后new()
的一个参数将是对象名称,您将其保存为self.name
(例如)然后您可以根据需要访问它(我想,对于日志消息或查找内部一些关联数组)。所以你会这样做
my_stack = Stack:new("my_stack", 2,4)
my_stack:push("dog") -- my_stack.elements = {2,4,"dog"}
我不知道如何让new()
弄清楚新实例将被分配给名为my_stack
的变量。事实上,我怀疑即使使用调试模块也不可能,因为只有在new
返回后才会进行分配。因此没有任何东西迫使对象的名称与变量相同,这完全取决于你。它甚至不是你想要的东西,因为你可以多次引用同一个堆栈对象:
a = Stack:new("a", 2,4)
b = a -- b and a are the same object in memory
错误消息是否应提及a
或b
?我认为最好为对象分配一个id,然后你总是知道在错误信息中正在讨论哪个对象:
a = Stack:new("my_stack_1", 2,4)
b = a
t = { b = { c = a } }
a:push("dog") -- error will mention my_stack_1: clear which object you are referring to
t.b.c:push("dog") -- error will mention my_stack_1: still clear which object you are referring to
如果您担心错误消息,您无法确定哪个行调用new(self, "dog")
,debug
模块可以派上用场:使用它可以获取行号和进行调用的文件,所以你可以说“对象my_stack_1:pop():堆栈中没有元素(从文件Y的第X行调用)”
答案 1 :(得分:4)
local function get_my_self_name(self)
local i = debug.getinfo(3, 'Sl');
return "'"..(io.open(i.source:match'@(.*)'):read'*a'
:gsub('.-\n','',i.currentline-1)
:match('(.-)[:.]%s*'..debug.getinfo(2,'n').name..'%s*%(')
:match'([%w_]+)%s*$' or '<unnamed>').."' at line #"..i.currentline
end
local Stack = {}
function Stack:new (...)
local instance = {}
instance.elements = {...}
setmetatable(instance, self)
self.__index = self
return instance
end
function Stack:push (...)
for i,v in ipairs({...}) do
table.insert(self.elements,v)
end
end
function Stack:pop ()
if #self.elements > 0 then
return table.remove(self.elements)
else
error("Can't pop, Stack "..get_my_self_name(self).." is empty")
end
end
local my_stack = Stack:new(2,4)
my_stack:push("dog") --my_stack.elements = {2,4,"dog"}
print(my_stack:pop()) --"dog"
print(my_stack:pop()) --"4"
print(my_stack:pop()) --"2"
print(my_stack:pop()) --error: Can't pop, Stack 'my_stack' at line #35 is empty