Why 'self' method of module cannot become a singleton method of class?

前端 未结 2 927
伪装坚强ぢ
伪装坚强ぢ 2020-12-23 12:57
module Test
  def self.model_method
    puts \"this is a module method\"
  end
end

class A
  include Test
end

A.model_method

this will be error w

相关标签:
2条回答
  • 2020-12-23 13:24

    Including a module is analogous to copying its instance methods over.

    In your example, there are no instance methods to copy to A. model_method is actually an instance method of Test's singleton class.


    Given:

    module A
      def method
      end
    end
    

    This:

    module B
      include A
    end
    

    Is analogous to this:

    module B
      def method
      end
    end
    

    When you think of it this way, this makes perfect sense:

    module B
      class << self
        include A
      end
    end
    
    B.method
    

    Here, the methods are being copied to the B module's singleton class, which makes them the "class methods" of B.

    Note that this is exactly the same thing as:

    module B
      extend A
    end
    

    In reality, the methods are not being copied; there is no duplication. The module is simply included in the method lookup list.

    0 讨论(0)
  • 2020-12-23 13:29

    If you want to have both class methods and instance methods mixed into a class when including a module, you may follow the pattern:

    module YourModule
      module ClassMethods
        def a_class_method
          puts "I'm a class method"
        end
      end
    
      def an_instance_method
        puts "I'm an instance method"
      end
    
      def self.included(base)
        base.extend ClassMethods
      end
    end
    
    class Whatever
      include YourModule
    end
    
    Whatever.a_class_method
    # => I'm a class method
    
    Whatever.new.an_instance_method
    # => I'm an instance method
    

    Basically to over-simplify it, you extend to add class methods and you include to add instance methods. When a module is included, it's #included method is invoked, with the actual class it was included in. From here you can extend the class with some class methods from another module. This is quite a common pattern.

    See also: http://api.rubyonrails.org/classes/ActiveSupport/Concern.html

    0 讨论(0)
提交回复
热议问题