web-dev-qa-db-ja.com

rubyスーパーキーワード

私が理解していることから、superキーワードは、現在のクラスのスーパークラスの現在のメソッドと同じ名前のメソッドを呼び出します。以下のautoloadメソッドには、superの呼び出しがあります。どのスーパークラスで同じ名前のメソッドが見つかるか、またはsuperの呼び出しがここで何をするのかを知りたい

module ActiveSupport
  module Autoload
    ...      
    def autoload(const_name, path = @@at_path)
      full = [self.name, @@under_path, const_name.to_s, path].compact.join("::")
      location = path || Inflector.underscore(full)

      if @@eager_autoload
        @@autoloads[const_name] = location
      end
      super const_name, location
    end
   .... 
  end
end

module ActiveRecord
  extend ActiveSupport::Autoload
  ...
  autoload :TestCase
  autoload :TestFixtures, 'active_record/fixtures'
end

このコードはRails masterブランチからのものです。ありがとうございました。

57
user290870

Ruby superキーワードのドキュメント で提供されている例:

module Vehicular
  def move_forward(n)
    @position += n
  end
end

class Vehicle
  include Vehicular  # Adds Vehicular to the lookup path
end

class Car < Vehicle
  def move_forward(n)
    puts "Vrooom!"
    super            # Calls Vehicular#move_forward
  end
end

先祖を調べる

puts Car.ancestors.inspect

# Output
# [Car, Vehicle, Vehicular, Object, Kernel, BasicObject]

VehicularModuleオブジェクトが含まれていることに注意してください!

45
maček

_objRef.class.ancestors_または_ClassName.ancestors_をチェックして、継承チェーンを確認します。スーパークラスにメソッドが含まれていない場合、スーパークラスに含まれるすべてのモジュールがチェックされます(最後に含まれるモジュールが最初にチェックされます)。一致しない場合、1つ上のレベルの祖父母クラスに移動します。
先祖のリストを使用してから、AncestorClass.methods.select{|m| m.include?("auto_load")}を呼び出して、呼び出されているメソッドをゾーニングできます。

(注:上記のコードはRuby 1.8です。1.9ではmethodsは文字列ではなくシンボルを返します。したがって、_m.to_s.include?(..._を実行する必要があります)

15
Gishu

Pry を使用します

superを使用する直前にbinding.pry呼び出しを挿入し、show-source -s-ssuperclassを意味します)を呼び出して、スーパークラスメソッドを表示し、定義されている場所を見つけます。 :

class A
  def hello
    puts "hi"
  end
end

class B < A
  def hello
    binding.pry
    super
  end
end

b = B.new
b.hello

From: (pry) @ line 7 B#hello:

     7: def hello
 =>  8:   binding.pry
     9:   super
    10: end

[1] (pry) #<B>: 0> show-source -s

From: (pry) @ line 2:
Number of lines: 3
Owner: A   # <--see owner here (i.e superclass)
Visibility: public

def hello
  puts "hi"
end
[2] (pry) #<B>: 0>    
14
horseyguy

super キーワードは、継承されたメソッドを見つけるために、祖先ツリーをずっと調べます。

Rails masterブランチ全体で検索を実行します。def autoloadで見ているものとまったく同じactive_support/lib/active_support/dependencies/autoload.rb]のみが見つかります。

オーバーライドされるメソッドはネイティブRubyです。 Module#autoload

5
maček

メソッドの所有者を見つけるためにこのメソッドを.irbrcに追加しましたが、特にシングルトンクラスのスーパークラスがスーパークラスのシングルトンクラスであるシングルトンメソッドを処理する場合、これを行うより良い方法がありますか?

  class Object
    def find_method(method_string)
        if klasses = self.class.ancestors.select { |a| a if a.methods.include? method_string }
          puts "class method in #{klasses.join(',')}" unless klasses.empty?
        end
        if klasses = self.class.ancestors.select { |a| a if a.instance_methods.include? method_string }
          puts "instance method in #{klasses.join(',')}" unless klasses.empty?
        end
      rescue
        raise "owning class not found"
    end
  end
2
Eric Steen

関連するスーパークラスメソッドは、おそらく Module#autoload です。

1
Greg Campbell