Каковы некоторые хорошие примеры Mixins и или Черты?

Я читал о Ruby и узнал о его миксин-паттерне, но не мог придумать много полезных миксин-функций (потому что я не привык так думать, скорее всего). Поэтому мне было интересно, что будет хорошим примером полезной функциональности Mixin?

Спасибо

Изменить: немного фона. Я прихожу из C ++ и других объектных языков, но я сомневаюсь, что Ruby говорит, что он не наследует миксины, но я продолжаю видеть миксины как множественное наследование, поэтому я боюсь, что пытаюсь слишком рано классифицировать их в моей зоне комфорта и не совсем грок, что такое миксин.

10.12.2008 10:32:04
Забавно видеть теги [language-agnostic] и [ruby], расположенные рядом друг с другом, как будто они лучшие друзья =)
Oli 10.12.2008 10:35:09
хорошо Руби поднял вопрос, но Mixin и черты могут быть сделаны на других языках, так как это скорее образец, я думаю
Robert Gould 10.12.2008 10:46:11
4 ОТВЕТА
РЕШЕНИЕ

Ну, обычный пример, я думаю, это настойчивость

module Persistence
    def load sFileName
            puts "load code to read #{sFileName} contents into my_data"
    end
        def save sFileName
        puts "Uber code to persist #{@my_data} to #{sFileName}"
    end

end

class BrandNewClass
    include Persistence
    attr :my_data

        def data=(someData)
        @my_data = someData
    end
end

b = BrandNewClass.new
b.data = "My pwd"
b.save "MyFile.secret"
b.load "MyFile.secret"

Представьте, что модуль написан ниндзя Ruby, который сохраняет состояние вашего класса в файл.
Теперь предположим, что я пишу новый класс, я могу повторно использовать функциональность постоянства, смешивая его, говоря include ModuleILike. Вы даже можете включить модули во время выполнения. Я загружаю и сохраняю методы бесплатно, просто смешивая их. Эти методы такие же, как те, что вы написали сами для своего класса. Код / Поведение / Функциональность - повторное использование без наследования!

Итак, что вы делаете, это добавляете методы в таблицу методов для вашего класса (буквально не правильно, но близко).

9
10.12.2008 11:02:54

Он широко используется, поскольку можно использовать множественное наследование в C ++ или реализовать интерфейсы в Java / C #. Я не уверен, где лежит ваш опыт, но если вы уже делали эти вещи раньше, миксины - это то, как вы делали бы их в Ruby. Это систематизированный способ внедрения функциональности в классы.

1
10.12.2008 10:37:05
Исходя из C ++ и других, но я сомневаюсь в том, что Ruby говорит, что он не наследует миксины, но я продолжаю видеть миксины как множественное наследование, как вы говорите, поэтому я боюсь, что пытаюсь слишком быстро классифицировать их в моей зоне комфорта, и не совсем грок, что такое миксин.
Robert Gould 10.12.2008 10:49:21

Они обычно используются для добавления некоторой формы стандартной функциональности к классу, без необходимости переопределять все это. Вы , вероятно , может думать о них немного , как интерфейсы в Java, но вместо того , чтобы просто определить список методов , которые должны быть реализованы, многие из них на самом деле будет быть реализован путем включения модуля.

В стандартной библиотеке есть несколько примеров:

Singleton - модуль, который можно смешать с любым классом, чтобы сделать его синглтоном. Метод initialize делается приватным, и добавляется метод экземпляра, который гарантирует, что в вашем приложении будет только один экземпляр этого класса.

Comparable - если вы включите этот модуль в класс, определения метода <=>, который сравнивает текущий экземпляр с другим объектом и говорит, что он больше, достаточно для предоставления <, <=, ==,> =,> и между? методы.

Enumerable - смешивая в этом модуле и определяя каждый метод, вы получаете поддержку для всех других связанных методов, таких как сбор, внедрение, выбор и отклонение. Если у него также есть метод <=>, он также будет поддерживать сортировку, min и max.

DataMapper также является интересным примером того, что можно сделать с помощью простого оператора включения, беря стандартный класс и добавляя возможность сохранять его в хранилище данных.

12
10.12.2008 10:55:50

В ruby ​​причина, по которой миксины не являются множественным наследованием, заключается в том, что комбинирование методов миксина - одноразовая вещь. Это не было бы такой большой проблемой, за исключением того, что модули и классы Ruby открыты для модификации. Это означает, что если вы смешаете модуль с вашим классом, а затем добавите метод к модулю, этот метод не будет доступен вашему классу; где, если бы вы сделали это в обратном порядке, это было бы.

Это похоже на заказ мороженого. Если вы получите в качестве своих миксинов шоколадные обсыпки и кусочки ириски и уйдете со своим конусом, то какой у вас конус мороженого не изменится, если кто-то добавит разноцветные обсыпки в корзину для обсыпки шоколада в магазине мороженого. Ваш класс, конус мороженого, не изменен, когда модуль mixin, мусорное ведро, является. Следующий человек, который будет использовать этот модуль mixin, увидит изменения.

Когда вы includeиспользуете модуль в ruby, он вызывает Module#append_featuresэтот модуль, который добавляет копию методов этого модуля в файл включения один раз.

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

Это как отношения родителя и ребенка в RL. Ваша мать, возможно, научилась жонглировать после вашего рождения, но если кто-то попросит вас жонглировать, и вы попросите ее либо: показать вам, как (скопируйте это, когда вам это нужно), либо сделать это для вас (чистое делегирование), тогда она Вы сможете в этот момент, даже если вы были созданы до ее способности жонглировать.

Вполне возможно, что вы могли бы изменить модуль ruby ​​'include', чтобы он действовал больше как множественное наследование, изменив, Module#append_featuresчтобы сохранить список включений, а затем обновить их с помощью method_addedобратного вызова, но это будет большим отличием от стандартного Ruby и может привести к основные проблемы при работе с чужим кодом. Возможно, вам лучше создать Module#inheritметод, который также вызывает includeи обрабатывает делегирование.

Что касается примера из реального мира, Enumerableэто здорово. Если вы определите #eachи включите Enumerableв свой класс, то это даст вам доступ к целому ряду итераторов, без необходимости кодировать каждый из них.

3
10.12.2008 13:58:27
Возможно, я неправильно понимаю вашу точку зрения, или, возможно, Ruby изменился с декабря 2008 года, но следующий код не демонстрирует «одноразовое» поведение, которое вы описываете. В частности, обратите внимание, что Fooэкземпляр может вызывать fubbметод, даже если этот метод был добавлен в Mixinмодуль после того, как Fooкласс смешан в модуле. Пример кода ( с помощью точки с запятой представляют разрывы строк): module Mixin; def bar; puts "Mixin.bar()"; end; end; class Foo; include Mixin; end; module Mixin; def fubb; puts "Mixin.fubb()"; end; end; f = Foo.new; f.bar; f.fubb.
FMc 11.11.2010 13:07:36
Если вы считаете, что ошибаетесь, можете ли вы отредактировать свой ответ и хотя бы добавить примечание, чтобы прочитать комментарии? Спасибо!
wbyoung 3.03.2013 17:08:09