Class 在Lua中,能否从';自我';?

Class 在Lua中,能否从';自我';?,class,oop,lua,Class,Oop,Lua,我可能遗漏了一些非常简单的东西,但是在Lua中调用对象的方法时,有没有办法从self变量中获取该对象的名称 为了说明我的意思,下面是一个有点做作的示例—一个简单的堆栈实现: Stack = {} function Stack:new (...) instance = {} instance.elements = {...} setmetatable(instance, self) self.__index = self return instance en

我可能遗漏了一些非常简单的东西,但是在Lua中调用对象的方法时,有没有办法从
self
变量中获取该对象的名称

为了说明我的意思,下面是一个有点做作的示例—一个简单的堆栈实现:

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"
是否可以使用
Stack:pop
错误消息中的
self
变量来输出调用对象的名称?我希望错误消息显示“
无法弹出,堆栈'my_Stack'为空

有没有办法从自变量中获取该对象的名称

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\u 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
如果您担心从错误消息中无法确定哪一行调用了新的(self,“dog”),那么
debug
模块就可以派上用场了:有了它,您可以得到调用的行号和文件,所以您可以说“object my_stack_1:pop():堆栈中没有剩余的元素(从文件Y的X行调用)“

本地函数get\u my\u self\u name(self)
本地i=debug.getinfo(3,'Sl');
返回“.”(io.open(i.source:match'@(.*)):读“*a”
:gsub('.-\n','',i.currentline-1)
:match('(.-)[:.]%s*'..debug.getinfo(2,'n')。name..'%s*%('))
:在第#行匹配“([%w_]+)%s*$”或“)..”。i.currentline
结束
本地堆栈={}
函数堆栈:新的(…)
本地实例={}
instance.elements={…}
setmetatable(实例,自身)
self.\uuu索引=self
返回实例
结束
函数堆栈:push(…)
对于ipairs({…})中的i,v
表.插入(自身元素,v)
结束
结束
函数堆栈:pop()
如果#self.elements>0,则
返回表.remove(self.elements)
其他的
错误(“无法弹出,堆栈”。.get_my_self_name(self)…“为空”)
结束
结束
本地my_stack=堆栈:新(2,4)
my_stack:push(“dog”)--my_stack.elements={2,4,“dog”}
打印(my_stack:pop())-“dog”
打印(my_stack:pop())--“4”
打印(my_stack:pop())--“2”
打印(my_stack:pop())--错误:无法弹出,第35行的堆栈“my_stack”为空

许多名称不同的变量(甚至零变量)可能包含对堆栈对象的引用。
self
类内方法指向该对象,因此不知道您要显示哪个变量名。顺便说一句,您最好在
stack:push
中使用
ipairs
。我以前就有过它,我保证:P-但是关于这个特定的示例,有什么方法可以得到它吗其中“my_stack”的名称,除了在构造过程中将其设置为字符串之外?比如,有没有办法使用
self.elements
,以某种方式计算出表元素的内部,并使用它来计算名称?如果错误消息能够告诉您正在执行某些操作的实例,这似乎会很有用出现问题。您希望通过此代码得到什么消息:
如果堆栈:new(get_data()):pop(),则结束
?嗯,我想使用
tostring(self)
可能是唯一远为有用的东西,因此会导致类似
无法弹出,堆栈“0x047b9eb0”为空的情况。
这样,当使用多个堆栈时,您至少可以知道何时出现10个错误,是否所有错误都来自同一个对象或不同的对象。这一点的准确率较低,而更多的只是一些错误f当然可以在调试时提供帮助。哈哈,太好了!我只想在您的返回语句末尾添加一个
或“
”,以解释您在上面的评论中指出的情况:
Stack:new():pop()
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