В чем разница между "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
:
- переопределение метода другим, определенным в модуле
- когда обезьяна ямочный метод, вы можете вызвать переопределенный метод из нового реализации?
- Ruby: модуль, миксины и блоки запутанные?
(Примечание: я упоминаю только методы, так как их легче всего представить, когда дело доходит до наследования и смешивания, но то же самое относится и к другим функциям.)
Я думал добавить его в качестве комментария к хорошему ответу, который @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, за исключением того, что вместо вставки модуля между классом и его суперклассом в цепочке он вставит его в нижней части цепочки, даже до самого класса.
Я бы предложил прочитать сообщение, чтобы лучше понять, как это происходит с примерами.