28
class C1
  def pr
    puts 'C1'
  end
end

class C2 < C1
  def pr
    puts 'C2'
    super
    puts self.method(:pr).source_location
  end
end

c = C2.new
c.pr

在上面的程序中,是否可以获得superC1::pr在我们的例子中)执行的代码的位置以及我们C2::pr使用source_location方法获得代码的位置?

4

5 回答 5

31

从 ruby​​ 2.2 你可以super_method像这样使用:

Class A
  def pr
    puts "pr"
  end
end

Class B < A
  def pr
    puts "Super method: #{method(:pr).super_method}"
  end
end

作为super_method返回一个方法,您可以将它们链接起来以找到祖先:

def ancestor(m)
  m = method(m) if m.is_a? Symbol
  super_m = m.super_method
  if super_m.nil?
    return m
  else
    return ancestor super_m
  end
end
于 2015-06-06T15:27:46.523 回答
9

您只需要到达超类,然后使用instance_method从超类中获取方法。

class C2 < C1
  def pr
    puts "C2"
    super
    puts "Child: #{self.method(:pr).source_location}"
    puts "Parent: #{self.class.superclass.instance_method(:pr).source_location}"
  end
end

编辑——关于检查祖先链的评论,它(令人惊讶地)似乎是不必要的。

class C1
  def pr
    puts "C1"
  end
end

class C2 < C1; end

class C3 < C2
  def pr
    puts "C3"
    super
    puts "Child source location: #{self.method(:pr).source_location}"
    puts "Parent source location: #{self.class.superclass.instance_method(:pr).source_location}"
  end
end

c = C3.new
c.pr

印刷

C3
C1
Child source location: ["source_location.rb", 10]
Parent source location: ["source_location.rb", 2]
于 2013-04-29T16:52:59.387 回答
5

如果您使用pry,则可以使用-s标志来显示超级方法。有关该功能的文档在这里

show-source Class#method -s
于 2015-02-24T11:49:05.223 回答
3

根据@bukk530,super_method可以得到你想要的,但是通过控制台访问它的好方法是

ClassName.new.method(:method_name).super_method.source_location
于 2018-07-25T22:08:56.857 回答
1

要查看该方法的全部祖先...

irb在会话中定义它:

class Object
  def method_ancestry(method_name)
    method_ancestors = []
    method = method(method_name)
    while method
      method_ancestors << [method.owner, method.source_location]
      method = method.super_method
    end
    method_ancestors
  end
end

例如,在 Rails 控制台中,我可以这样做:

# assuming User is an ActiveRecord class
User.new.method_ancestry(:save)

=> [[ActiveRecord::Suppressor,
  ["/Users/me/.gem/ruby/2.3.1/gems/activerecord-5.0.1/lib/active_record/suppressor.rb", 40]],
 [ActiveRecord::Transactions,
  ["/Users/me/.gem/ruby/2.3.1/gems/activerecord-5.0.1/lib/active_record/transactions.rb", 317]],
 [ActiveRecord::AttributeMethods::Dirty,
  ["/Users/me/.gem/ruby/2.3.1/gems/activerecord-5.0.1/lib/active_record/attribute_methods/dirty.rb",
   21]],
 [ActiveRecord::Validations,
  ["/Users/me/.gem/ruby/2.3.1/gems/activerecord-5.0.1/lib/active_record/validations.rb", 43]],
 [ActiveRecord::Persistence,
  ["/Users/me/.gem/ruby/2.3.1/gems/activerecord-5.0.1/lib/active_record/persistence.rb", 124]]]

仅此列表并不能告诉您列出的任何方法定义是否实际调用super或只是覆盖其继承定义。但是,如果您super在其中一个中看到,它会转到列表中的下一个。

如果你经常使用它,你可以把它放在你的~/.irbrcor~/.pryrc中。

于 2017-02-13T14:33:21.430 回答