【问题标题】:ruby super keywordruby 超级关键字
【发布时间】:2011-02-05 13:26:27
【问题描述】:

据我了解,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 分支。非常感谢。

【问题讨论】:

    标签: ruby-on-rails ruby activerecord


    【解决方案1】:

    Ruby 文档中为super keyword 提供的示例:

    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]
    

    注意 Vehicular Module 对象的包含!

    【讨论】:

    • 您好,根据您的示例,“模块”不在此处的祖先树中,您所指的自动加载方法在 Module#autoload 中。我所说的是 ActiveSupport.class 是 Module 但它不是超类。 ActiveSupport.superclass 会给你一个错误
    • 嗨,争论呢?如果你只是从 Car 调用 super ,它会自动将参数传递给 Vehicular 的 super 吗???
    【解决方案2】:

    检查objRef.class.ancestorsClassName.ancestors 以了解继承链。如果超类不包含该方法,则检查超类包含的所有模块(首先检查最后包含的模块)。如果不匹配,则向上移动一级到祖父母类,依此类推。
    您可以使用祖先列表,然后调用AncestorClass.methods.select{|m| m.include?("auto_load")} 来定位正在调用的方法。

    (注意:上面的代码是 Ruby 1.8。在 1.9 中,methods 返回符号而不是字符串。所以你必须做一个m.to_s.include?(...

    【讨论】:

    • 也许我没有按照您的意图阅读您的答案,但是据我所知,在祖先链中检查的第一个位置不是超类,而是当前类中包含的模块。只有在这些都用尽之后,搜索才会转移到超类。我发现blog.rubybestpractices.com/posts/gregory/… 有助于理解发生了什么。
    【解决方案3】:

    使用Pry

    在使用super 之前插入一个binding.pry 调用,然后调用show-source -s-s 表示superclass)以显示超类方法并找出它的定义位置:

    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>    
    

    【讨论】:

    • @deepak 对 pry 的find-method hello 的建议更方便!
    【解决方案4】:

    super 关键字一直向上检查祖先树以查找继承的方法。

    在整个 rails master 分支上进行搜索。您只会找到一个def autoload,这正是您在active_support/lib/active_support/dependencies/autoload.rb 中看到的那个。

    被覆盖的方法是原生 Ruby。是Module#autoload

    【讨论】:

    • 你能解释一下 Module 是如何成为祖先树的一部分的吗?任何包含“ActiveSupport::Autoload”的类(比方说C)都将方法“autoload”作为实例方法。据我了解,除“类”类之外的任何类的超类都是对象。所以当我们的类'C'的一个实例调用'autoload'时,超级应该在'C'的超类中寻找对象。我错过了什么。
    • @ash34,这一切都包裹在module ActiveSupport 中,这是一个Module 对象。
    • @ash34,包含的模块是类祖先的一部分。检查例如 Array.ancestors 以查看它检查方法定义的模块和类的列表。
    【解决方案5】:

    我添加了这个方法来查找我的 .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
    

    【讨论】:

      【解决方案6】:

      相关的超类方法大概是Module#autoload

      【讨论】:

      • ActiveSupport::Autoload 的超类 module 是 ActiveSupport::Autoload 的类吧?谢谢。
      • @ash34, super 不断地往上爬,直到找到最接近的继承方法。有关详细信息,请参阅我的答案。
      猜你喜欢
      • 1970-01-01
      • 2023-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-08
      • 2013-07-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多