Классы, модули и Mixin-ы в Ruby

Некто сказал - если хочешь что-то понять, научи этому других.

В языке Java у вас есть классы и интерфейсы. В Ruby есть классы, модули и смесь и тех и других (mixin).

Я считаю модули неким вырожденным абстрактным классом. Он не может порождать объекты, он может быть только расширением других классов.

Итак, напишем наш первый модуль, который требует от класса наличия переменной @value

# Convert a integer value to English.
module Stringify
  def stringify
  ... # some code with @value
  end
end

И второй модуль, который сам по себе и не зависит от переменных класса

module Math 
  def add(val_one, val_two)
      BigInteger.new(val_one + val_two)
  end
end

А теперь напишем mixin BigInteger класс

class Number
  def intValue
    @value
  end
end

# BigInteger наследуется от Number
class BigInteger < Number

  # Вклюаем методы инстанса из Stringify
  include Stringify

  # Включаем методы класса из Math
  extend Math

    # Конструктор
    def initialize(value)
        @value = value
    end
  end

Оно будет работать вот так:

bigint1 = BigInteger.new(10)
puts bigint1.intValue   # --> 10 через метод родителя

bigint2 = BigInteger.add(-2, 4)
puts bigint2.intValue   # --> 2 через метод класса Math

puts bigint2.stringify   # --> 'Two'


# Напишем еще один модуль:
module CurrencyFormatter
  def format
    "$#{@value}"
  end
end

# И включим его в инстанс

bigint2.extend CurrencyFormatter
puts bigint2.format   # --> '$2'
puts bigint1.format   # ошибка

У модулей тоже есть конструкторы - методы, которые будут вызваны при включении модуля в класс:

module Math
  def self.extended(base)
    # Initialize module.
  end
end

# base - это класс, в который включен модуль
module Stringify
  def self.included(base)
    base.extend SomeOtherModule
  end
end
Яндекс.Метрика