Каковы некоторые хорошие примеры миксинов и / или черт?

StackOverflow https://stackoverflow.com/questions/355633

Вопрос

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

Спасибо

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

Это было полезно?

Решение

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

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

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

Другие советы

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top