В чем разница между "include" и "prepend" в Ruby?

С модуль

Module#append_features (mod) → mod => когда этот модуль включен в другой, Ruby вызывает append_features в этом модуле, передавая ему принимающий модуль в mod. Реализация Ruby по умолчанию -добавить константы, методы и переменные модуля этого модуля для mod, если этот модуль еще не был добавлен в mod или один из его предков.

Module#prepend_features (mod) → mod => когда этот модуль добавляется в другой, Ruby вызывает prepend_features в этом модуле, передавая ему принимающий модуль в mod. Реализация Ruby по умолчанию -для наложения константы, методы и переменные модуля этого модуля для mod, если этот модуль еще не был добавлен в mod или один из его предков.

может ли кто-нибудь помочь мне понять ниже вопросы:

  • какие еще особенности Module определяется как append и prepend кроме тех, что по умолчанию?

  • как они функционально отличаются?

  • при использовании append_features и когда prepend_features?

  • в чем разница между двумя жирными линиями, что и выше?

2 ответов


  • какие функции модуля определяются как append и prepend?

как указано в тексте, который вы процитировали:

константы, методы и переменные модуля

  • как они функционально отличаются?

оба добавляют методы смешанного модуля к переданному модулю (классу). Разница заключается в порядке поиска этих методов, если целевой класс уже имеет их определено:

include ведет себя так, как будто целевой класс унаследовал смешанный модуль:

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 делает методы из смешанного в модуле "сильнее" и выполняет их сначала:

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

пример любезно сорвал отсюда: http://blog.crowdint.com/2012/11/05/3-killer-features-that-are-coming-on-ruby-2-0.html

  • когда использовать append_features и когда prepend_features?

использовать prepend Если вы хотите сохранить методы целевого модуля (класса) в конце цепочки поиска метода.

некоторые примеры реального мира можно найти, выполнив поиск так для ruby, module и prepend:

(Примечание: я упоминаю только методы, так как их легче всего представить, когда дело доходит до наследования и смешивания, но то же самое относится и к другим функциям.)


Я думал добавить его в качестве комментария к хорошему ответу, который @Mladen Jablanovic уже сделал, но я не мог из-за моей низкой точки репутации.

Я нашел более краткий, ясный и более описательный ответ на сообщение здесь -Ruby модули: включить vs Prepend vs Extend и я размещаю его здесь на всякий случай, если кому-то это нужно и может получить его с меньшими усилиями.

прямые цитаты:

хотя include является наиболее распространенным способом импортируя внешний код в класс, Ruby предоставляет также два других способа достижения этого: extend и prepend. Однако они не имеют одинаковое поведение вообще, и эти различия часто неправильно понимаются разработчиками Ruby.

чтобы понять, как их использовать, мы должны сначала глубже взглянуть на то, как Ruby разрешает методы для выполнения во время выполнения, используя что-то, называемое цепочкой предков.

когда создается класс Ruby, он содержит список постоянных имен которые являются его предками. Это все классы, которые наследует класс, и модули, которые они включают. Например, вызывая предков в классе String, мы получаем список его предков:

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

include-наиболее используемый и простой способ импорта кода модуля. При вызове его в определении класса Ruby вставит модуль в цепочку предков класса сразу после его суперкласса.

доступно с Ruby 2, добавить немного менее известен рубистов, чем двух других друзей. На самом деле он работает как include, за исключением того, что вместо вставки модуля между классом и его суперклассом в цепочке он вставит его в нижней части цепочки, даже до самого класса.

Я бы предложил прочитать сообщение, чтобы лучше понять, как это происходит с примерами.