What is the difference between 'include' and 'prepend' in Ruby?

后端 未结 2 823
借酒劲吻你
借酒劲吻你 2021-01-01 11:08

From the Module

Module#append_features(mod) → mod => When this module is included in another, Ruby calls append_features in this module, passing it th

相关标签:
2条回答
  • 2021-01-01 11:47

    I thought to add it as a comment to a good answer which @Mladen Jablanovic has already made but I couldn't due to my low reputation point.

    I've found a more concise, clearer and more descriptive answer on a post here - Ruby modules: Include vs Prepend vs Extend and I post it here just in case someone needs it and could get it with less effort.

    Direct quotes:

    Though include is the most common way of importing external code into a class, Ruby provides also two other ways to achieve that: extend and prepend. However, they don’t have the same behavior at all, and these differences are often misunderstood by Ruby developers.

    To understand how to use them, we must first have a deeper look into how Ruby is resolving methods to execute at runtime, using something called the ancestors chain.

    When a Ruby class is created, it holds a list of constant names which are its ancestors. They are all the classes that the class inherits from, and the modules they include. For example, by calling ancestors on the String class, we get the list of its ancestors:

    String.ancestors
    => [String, Comparable, Object, PP::ObjectMixin, Kernel, BasicObject]
    

    include is the most used and the simplest way of importing module code. When calling it in a class definition, Ruby will insert the module into the ancestors chain of the class, just after its superclass.

    Available since Ruby 2, prepend is a bit less known to Rubyists than its two other friends. It actually works like include, except that instead of inserting the module between the class and its superclass in the chain, it will insert it at the bottom of the chain, even before the class itself.

    I would suggest reading the post to get a better understanding as it comes with examples.

    0 讨论(0)
  • 2021-01-01 11:51
    • What features of Module are defined as append and prepend?

    As specified in the text you quoted:

    the constants, methods, and module variables

    • How they differ functionally?

    Both add methods of the mixed-in module to the passed module (class). The difference is in the lookup order of these methods, in case that the target class already has them defined:

    include behaves as if the target class inherited mixed-in module:

    module FooBar
      def say
        puts "2 - Module"
      end
    end
    
    class Foo
      include FooBar
    
      def say
        puts "1 - Implementing Class"
        super
      end
    end
    
    Foo.new.say # =>
                # 1 - Implementing Class
                # 2 - Module
    

    prepend makes the methods from the mixed in module "stronger" and executes them first:

    module FooBar
      def say
        puts "2 - Module"
        super
      end
    end
    
    class Foo
      prepend FooBar
    
      def say
        puts "1 - Implementing Class"
      end
    end
    
    Foo.new.say # =>
                # 2 - Module
                # 1 - Implementing Class
    

    The example kindly ripped off from here: http://blog.crowdint.com/2012/11/05/3-killer-features-that-are-coming-on-ruby-2-0.html

    • When to use append_features and when prepend_features?

    Use prepend when you want to keep methods of the target module (class) at the end of the method lookup chain.

    Some real-world examples can be found by searching SO for ruby, module and prepend:

    • Overriding method by another defined in module
    • When monkey patching a method, can you call the overridden method from the new implementation?
    • Ruby: Module, Mixins and Blocks confusing?

    (Note: I am mentioning only methods, as they are easiest to picture when it comes to inheritance and mixing-in, but the same applies to other features.)

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