【问题标题】:How to get the caller object name in ruby?如何在 ruby​​ 中获取调用者对象名称?
【发布时间】:2013-12-02 20:43:21
【问题描述】:

经常会从不同的对象A、B、C调用同一个方法X。是否可以从方法X内部获取调用者对象(A、B、C)的名称

例如:

class Sample
  def method
    # what needs to be done here?
  end
end

n1 = Sample.new
n2 = Sample.new

n1.method #=> expected output is to print n1
n2.method #=> expected output is to print n2

【问题讨论】:

  • @YevgeniyAnfilofyev 它不是您指定的链接的副本。 OP 要求一种打印调用对象名称的方法,而您提供的链接描述了一种打印调用方法名称的方法
  • @user2753200 您实际上是在询问变量名称,caller 指的是执行堆栈。
  • 此外,它不是 object 名称,因为对象没有名称,只是一个 ID。
  • @undur_gongor 只有一位用户认为它离题了

标签: ruby object


【解决方案1】:

不,这不起作用。成像以下:

n1 = Sample.new
n2 = n1

n2.method #=> ambiguous, both n1 and n2 would be valid

您可以为您的实例分配一个名称

class Sample
  attr_accessor :name
end

n1 = Sample.new
n1.name = :n1

n2 = Sample.new
n2.name = :n2


n1.name #=> :n1
n2.name #=> :n2

【讨论】:

  • 技术上n2.method 在语法上没有歧义。相反,Ruby 的内部结构使其无法解析(并且在任何情况下都不可取)来查找使用了哪个指针。
  • @NeilSlater 这可以用任何语言实现吗?
  • 我不想说“从不”,但不,我想不出一种可以通过编程方式发现变量名的语言。可能有一些人可以通过调用者堆栈和代码自省来进行攻击——这在大多数情况下可能会起作用。即使在可能的语言中,这仍然会滥用变量名,并且 OP 可能还有其他方法来实现未说明的更高级别目标。
【解决方案2】:

正如其他人所说,直接使用object_id 很可能是更好的方法。

无论如何,沿着这条线的东西可能适用于你的情况:

class Sample
  def method(&b)
    eval("local_variables.select {|v| eval(v.to_s).object_id == #{object_id}}", 
         b.binding)
  end
end

n1 = Sample.new
n2 = Sample.new
n3 = n2

p n1.method {}         #=> [:n1]
p n2.method {}         #=> [:n2, :n3]
p Sample.new.method {} #=> []

它返回当前范围内引用被调用对象的所有(局部)变量。如果您的每个对象都被一个变量引用,这可能 成为你正在寻找的东西。

Neil Slater 建议:您也可以使用 gem binding_of_caller 来简化 转移绑定:

require 'binding_of_caller'

class Sample
  def method
    binding.of_caller(1).eval(
      "local_variables.select {|v| eval(v.to_s).object_id == #{object_id}}"
    )
  end
end

n1 = Sample.new
n2 = Sample.new
n3 = n2

p n1.method         #=> [:n1]
p n2.method         #=> [:n2, :n3]
p Sample.new.method #=> []

(使用 gem 的 0.7.2 版测试)。

【讨论】:

  • 尝试将它与binding_of_caller gem 结合起来:-)
【解决方案3】:

任何对象都可以通过它的object_id来识别:

class Sample
  def method
    puts self.object_id
  end
end

n1 = Sample.new
n2 = Sample.new

puts n1.object_id
n1.method

puts n2.object_id
n2.method

--output:--
2152302060
2152302060
2152302040
2152302040

变量名...没那么多。

【讨论】:

    【解决方案4】:

    只返回self 应该可以工作,

    这是一个例子:

    class Sample
      attr_accessor :name
      def method
        puts self  
        puts self.name  
      end
    end
    
    n1 = Sample.new
    n1.name = "Bangalore"
    n2 = Sample.new
    n2.name = "Chennai"
    
    
    n1.method #=> expected output is to print n1
    n2.method #=> expected output is to print n2
    
    
    -------
    Output: 
    #<Sample:0x7f492f62c030> # n1 object
    Bangalore # n1.name 
    #<Sample:0x7f492f62bec8> # n2 object
    Chennai #n2.name
    

    【讨论】:

    • 我认为 OP 将变量名与对象身份混淆了,并且不是 100% 清楚真正需要什么。不建议使用前者(可能在堆栈跟踪中除外),后者根据您的回答,相对简单。
    猜你喜欢
    • 2019-08-30
    • 1970-01-01
    • 2014-02-02
    • 1970-01-01
    • 1970-01-01
    • 2011-10-27
    • 2021-04-16
    • 1970-01-01
    相关资源
    最近更新 更多