How to determine the class a method was defined in?

橙三吉。 提交于 2019-12-21 12:38:47

问题


I would like to dynamically determine the class the current method was defined in.

Here's a static example of what I'm trying to do:

class A
  def foo
    puts "I was defined in A"
  end
end

class B < A
  def foo
    puts "I was defined in B"
    super
  end
end

A.new.foo
# I was defined in A

B.new.foo
# I was defined in B
# I was defined in A  <- this is the tricky one

How can I replace A and B in the strings above with a dynamic expression?

Apparently, #{self.class} does not work. (it would print I was defined in B twice for B)

I suspect that the answer is "you can't", but maybe I'm overlooking something.


回答1:


What about this?

class A
  def foo
    puts "I was defined in #{Module.nesting.first}"
  end
end

class B < A
  def foo
    puts "I was defined in #{Module.nesting.first}"
    super
  end
end

Corrected following WandMaker's suggestion.




回答2:


You could use Module.nesting.first.

However, note that this works purely lexically, the same way constants resolution works, so it won't cut it if you have more dynamic needs:

Foo = Class.new do
  def foo
    Module.nesting
  end  
end

Foo.new.foo # => []



回答3:


I have this nagging feeling that if you could do this, it would violate object-orientated encapsulation, although I can't quite place my finger on exactly why. So, it shouldn't come as a surprise that it's hard.

I can see a way if you are open to modifying the method definitions:

class A
  this = self
  define_method(:foo) do
    puts "I was defined in #{this}"
  end
end

class B < A
  this = self
  define_method(:foo) do
    puts "I was defined in #{this}"
    super()
  end
end

A.new.foo
# I was defined in A

B.new.foo
# I was defined in B
# I was defined in A


来源:https://stackoverflow.com/questions/34742181/how-to-determine-the-class-a-method-was-defined-in

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!