Ruby:获取方法的类或模块名称

时间:2016-07-10 23:20:23

标签: ruby

我试图了解mixin优先级情况。如果我运行foo.bar我试图弄清楚哪个bar将被执行。这是一个剪切的irb会话,我试图找出数组assoc方法的定义。

2.3.0 :032 > ray = ['cat', nil, 'dog']
 => ["cat", nil, "dog"] 
2.3.0 :033 > ray.methods
 => [:fill, :assoc, :rassoc, :uniq, ... 
2.3.0 :034 > ray.method("assoc").class_or_module_name
NoMethodError: undefined method `class_or_module_name' for #<Method: Array#assoc>
    from (irb):34
    from /Users/mark/.rvm/rubies/ruby-2.3.0/bin/irb:11:in `<main>'
2.3.0 :035 > ray.methods("assoc").class_or_module_name
NoMethodError: undefined method `class_or_module_name' for #<Array:0x007ffb8aa286a8>
    from (irb):35
    from /Users/mark/.rvm/rubies/ruby-2.3.0/bin/irb:11:in `<main>'
2.3.0 :036 > ray.methods("assoc")
 => [:fill, :assoc, :rassoc, :uniq, :uniq!, :compact, ...

如果可能的话,我希望看到方法及其源位置失去优先权。

2 个答案:

答案 0 :(得分:1)

通常,要了解定义方法的位置,您可以使用source_locationdocs),例如

ray.method("assoc").source_location

虽然在这种情况下它会返回nil,因为assoc是本机方法。它适用于其他方法,例如

ray.methods.map{ |m| [m, ray.method(m).source_location] }

对于原生方法,您可以使用Pry,例如

pry(main)> ? ray.assoc

From: array.c (C Method):
Owner: Array
Visibility: public
[...]

?show-doc的缩写。

答案 1 :(得分:1)

要找出哪个类或模块定义了一个方法(而不是哪个文件),请使用Method#owner

例如,

[].method(:last).owner #=> Array
[].method(:flat_map).owner #=> Enumerable

您实际上会发现Array 可以从Enumerable获取的许多方法,它实际上定义了自己(可能是为了提供更有效的实现):

irb(main):018:0> Enumerable.instance_methods.select {|meth_name| [].method(meth_name).owner == Array }
=> [:to_a, :to_h, :sort, :count, :find_index, :select, :reject, :collect, :map, :first, :include?, :reverse_each, :zip, :take, :take_while, :drop, :drop_while, :cycle]