Модули и миксины

Mixin

Модули по своему функционалу не так сильно отличаются от объектов. Мы можем объявлять модули как классы, можем обявлять внутри этих модулей переменные как и в классе, мы можем обявлять методы как и в классе, но в отличии от классов, мы не можем создавать объекты модулей. Какой тогда смысл от них ? Все просто, мы можем "подмешивать" модели в наши классы, тем самым обогащая их новым функционалом.

# Объявление модуля
module MyModule
  # метод модуля
  def print_hello
    puts 'hello world'
  end
end
class MyClass 
  # для того, чтобы подмешать модуль испольуется ключевое слово include
  include MyModule
end 
instance = MyClass.new
# Как можем заметить метод print_hello отсутствует в нашем классе
# но присутствует в нашем модуле
instance.print_hello # = hello world

Подмешивание на английском переводится как mix, отсюда и происходит слово mixin, поэтому можно сказать что mixin - это возможность использовать наши модули как инструмент расширения функциональности наших классов.

Основное отличие миксин от наследования заключается во множественном подмешивании. При наследовании класса от другого класса мы можем наследоваться только один раз, в то время как подмешивать миксины в класс мы можем сколько угодно.

В Ruby существуют встроенные модули, которые позволяют расширить функциональность наших классов. Например модуль Comparable, который дает возможность сравнивать объекты друг с другом, если мы подмешиваем этот модуль и переопределяем поведение метода <=>. Метод принимает в аргументах объект с которым будет происходить сравнение и должен:

  • вернуть 1, если наш объект больше объекта переданного в аргументе

  • вернуть -1, если наш объект меньше объекта переданного в аргументе

  • вернуть 0, если они равны

После этого нам становятся доступны такие логические операции как >, <, >= и <=.

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

Помимо Comparable, есть также модуль Enumarable, который добавляет множество методов для нашего класса, чтобы работать с ним как с коллекцией. Для этого нам необходимо при подмешивании определить метод each, который должен применять блок кода к каждому элементу, который содержится внутри нашего класса. Блоки кода будут разбираться в дальнейших уроках, сейчас главное понимать не как реализовывать метод each, а что нам дает его переопределние при использовании модуля Enumarable.

Взамен мы получаем такие методы как count, min, max, find, map и тд. Думаю вы заметили, что такие методы вы уже встречали в массивах ? На самом деле любая коллекция в Ruby имеет внутри себя модуль Enumarable. К слову, цикл for работает с объектами благодаря наличию у них модуля Enumarable.

Более подробно с встроенными модулями вы сможете ознакомиться в дополнительном материале.

Константы

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

Структуризация

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

задание animals

Внимание ! Это и последующие задания данного модуля с названием animals необходимо выполнять в одной и той же директории в корне модуля - 3_oop/animals

  • Изучите дополнительный материал про модуль Comparable и с помощью него научитесь сравнивать объекты Cat между собой по их весу.

  • Напишите в main.rb пример сравнения ваших котов, убедитесь, что оно работает

  • Попробуйте теперь сравнить объект класса Cat и класса Dog, какие выводы можно сделать ?

Задание company

Внимание ! Это и последующие задания данного модуля с названием company необходимо выполнять в одной и той же директории в корне модуля - 3_oop/company

  • Реализуйте в классе Company методы:

    • get_top_salary_staff(count) - возвращает список зарплат сотрудников, отсортированных по убыванию заданной длины

    • get_lowest_salary_staff(count) - возвращает список зарплат сотрудников, отсортированных по возрастанию заданной длины

    • выозвите эти методы до и после увольнения 50% сотрудников

Дополнительный материал

Last updated