【问题标题】:The name of the class that "newed" my class“新”我的班级的班级名称
【发布时间】:2012-01-04 00:37:38
【问题描述】:

在 Ruby 中,有没有办法获取创建 MyClass 实例的类的名称?

我知道我可以将它作为参数传递给我的初始化方法,但我想知道是否已经有任何数据与在 MyClass 中创建 MyClass 实例的类有关。

应该是这样的

class MyClass
  def initialize
    @who_called_me = who_called_me.name
  end

  def who_called_me
    puts @who_called_me
  end
end 

【问题讨论】:

  • 如果您需要知道这一点,那么您的设计可能有问题。
  • 一般来说,我想不出简单的方法来做到这一点。但是您可以获取堆栈回溯的字符串并在调用new 之前将其解析为帧。这可能会为您提供名为new 的代码部分。但这会使您的代码依赖于堆栈回溯的格式。不是一件好事。
  • 这是个特例,不过感谢质疑我的设计,真的很有帮助
  • 我按照我上面的建议添加了一个答案。我还没有测试过,但我会的。
  • 并非所有类都有名称,例如c = Class.new; puts c.name。当然,这是一个病态的案例,但是......

标签: ruby


【解决方案1】:

虽然这在实现和版本之间不可移植,但这是一个粗略的解决方案:

who_made_me=caller[3].split(':')[1][4..-2]

它的作用是获取当前堆栈,跳过initializeallocatenew 的字符串,然后从字符串中获取方法名称。同样,这是一个完全的黑客攻击,并且基于未指定的行为。除非绝对有必要,否则我不建议使用它。

【讨论】:

  • 你这个男人!!!这是一些混乱的代码,但不要担心它是如此值得。有些人在机器人友好的比赛中,假设我需要保护我的班级不被so创建
  • @LorenCFortner:如果有帮助,您可以尝试将保护代码编写为从扩展调用的 C 函数。 Ruby 不能覆盖 C 函数。
【解决方案2】:

总的来说,这是邪恶的。我在 C# 中看到过类似的东西,但它产生了极其残忍的副作用,更不用说丑陋的代码了。

在 Ruby 中,如果您真的必须这样做,您可能会从 Kernel.caller 开始。但请不要那样做。

【讨论】:

  • 我在下面发布了一些可能使用Kernel#caller 工作的东西。这是一个完整的 hack,我同意你的观点,但这是一个答案。
  • “残酷的副作用” - 请告诉更多!
  • @Andrew,基本上,由于其他代码无法预测构造函数的行为,它有特殊情况,因此它违反了所有 OOP 规则;我在 Perl 中看到过一个更糟糕的例子,其中参数的解析方式因调用者而异。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-26
  • 2018-05-20
  • 2016-10-06
  • 2013-02-25
  • 1970-01-01
相关资源
最近更新 更多