Ruby - модули и миксины
Модули - это способ группировки методов, классов и констант. Модули дают вам два основных преимущества.
Модули предоставляют пространство имен и предотвращают конфликты имен .
Модули реализуют возможность микширования .
Модули определяют пространство имен, песочницу, в которой могут работать ваши методы и константы, не беспокоясь о том, что на них могут наступить другие методы и константы.
Синтаксис
module Identifier
statement1
statement2
...........
end
Константы модуля называются так же, как константы класса, с начальной буквы в верхнем регистре. Определения методов тоже выглядят одинаково: методы модуля определяются так же, как методы класса.
Как и в случае с методами класса, вы вызываете метод модуля, предваряя его имя именем модуля и точкой, и вы ссылаетесь на константу, используя имя модуля и два двоеточия.
пример
#!/usr/bin/ruby
# Module defined in trig.rb file
module Trig
PI = 3.141592654
def Trig.sin(x)
# ..
end
def Trig.cos(x)
# ..
end
end
Мы можем определить еще один модуль с тем же именем функции, но с другой функциональностью -
#!/usr/bin/ruby
# Module defined in moral.rb file
module Moral
VERY_BAD = 0
BAD = 1
def Moral.sin(badness)
# ...
end
end
Как и методы класса, всякий раз, когда вы определяете метод в модуле, вы указываете имя модуля, за которым следует точка, а затем имя метода.
Заявление Ruby require
Оператор require аналогичен оператору include C и C ++ и оператору импорта Java. Если третья программа хочет использовать какой-либо определенный модуль, она может просто загрузить файлы модуля с помощью инструкции Ruby require -
Синтаксис
require filename
Здесь указывать .rb расширение вместе с именем файла.
пример
$LOAD_PATH << '.'
require 'trig.rb'
require 'moral'
y = Trig.sin(Trig::PI/4)
wrongdoing = Moral.sin(Moral::VERY_BAD)
Здесь мы используем $LOAD_PATH << '.'чтобы Ruby знал, что включенные файлы нужно искать в текущем каталоге. Если вы не хотите использовать $ LOAD_PATH, вы можете использоватьrequire_relative для включения файлов из относительного каталога.
IMPORTANT- Здесь оба файла содержат одно и то же имя функции. Таким образом, это приведет к неоднозначности кода при включении в вызывающую программу, но модули избегают этой неоднозначности кода, и мы можем вызвать соответствующую функцию, используя имя модуля.
Заявление о включении Ruby
Вы можете встроить модуль в класс. Чтобы встроить модуль в класс, вы используете оператор include в классе -
Синтаксис
include modulename
Если модуль определен в отдельном файле, то перед внедрением модуля в класс необходимо включить этот файл с помощью оператора require .
пример
Рассмотрим следующий модуль, записанный в файле support.rb .
module Week
FIRST_DAY = "Sunday"
def Week.weeks_in_month
puts "You have four weeks in a month"
end
def Week.weeks_in_year
puts "You have 52 weeks in a year"
end
end
Теперь вы можете включить этот модуль в класс следующим образом:
#!/usr/bin/ruby
$LOAD_PATH << '.'
require "support"
class Decade
include Week
no_of_yrs = 10
def no_of_months
puts Week::FIRST_DAY
number = 10*12
puts number
end
end
d1 = Decade.new
puts Week::FIRST_DAY
Week.weeks_in_month
Week.weeks_in_year
d1.no_of_months
Это даст следующий результат -
Sunday
You have four weeks in a month
You have 52 weeks in a year
Sunday
120
Миксины в Ruby
Прежде чем перейти к этому разделу, мы предполагаем, что вы знакомы с объектно-ориентированными концепциями.
Когда класс может наследовать функции более чем одного родительского класса, предполагается, что у этого класса будет множественное наследование.
Ruby не поддерживает множественное наследование напрямую, но у модулей Ruby есть еще одно замечательное применение. Одним махом они в значительной степени устраняют необходимость множественного наследования, предоставляя возможность, называемую миксином .
Миксины дают вам чудесно управляемый способ добавления функциональности к классам. Однако их истинная сила проявляется, когда код в миксине начинает взаимодействовать с кодом в классе, который его использует.
Давайте рассмотрим следующий пример кода, чтобы понять миксин:
module A
def a1
end
def a2
end
end
module B
def b1
end
def b2
end
end
class Sample
include A
include B
def s1
end
end
samp = Sample.new
samp.a1
samp.a2
samp.b1
samp.b2
samp.s1
Модуль A состоит из методов a1 и a2. Модуль B состоит из методов b1 и b2. Класс Sample включает оба модуля A и B. Класс Sample может получить доступ ко всем четырем методам, а именно a1, a2, b1 и b2. Таким образом, вы можете видеть, что класс Sample наследуется от обоих модулей. Таким образом, вы можете сказать, что образец класса показывает множественное наследование или миксин .