0Pricing
Ruby Academy · Урок

Comparable и Enumerable

Стандартные примеси

«Comparable и Enumerable» — бесплатный урок Ruby Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Ruby Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Ruby Academy содержит 4 уроков всего.

Стандартные миксины

Ruby поставляется с мощными модулями, которые можно подключать к собственным классам. Два особенно полезных — Comparable и Enumerable. Каждый предоставляет множество методов, требуя реализовать всего один.

puts Comparable.instance_methods.sort.inspect

Comparable требует <=>

Comparable требует определить оператор «космический корабль» <=>, который возвращает -1, 0 или 1. Взамен Вы получаете <, <=, ==, >, >= и between?.

class Weight
  include Comparable
  attr_reader :grams
  def initialize(g); @grams = g; end
  def <=>(other); grams <=> other.grams; end
end
puts Weight.new(50) < Weight.new(80)

Готовые методы сравнения

После определения одного оператора все методы сравнения начинают работать автоматически.

class Weight
  include Comparable
  attr_reader :grams
  def initialize(g); @grams = g; end
  def <=>(other); grams <=> other.grams; end
end
a = Weight.new(100)
b = Weight.new(100)
puts a == b
puts Weight.new(30).between?(Weight.new(10), Weight.new(50))

clamp из модуля сравнения

Comparable также предоставляет clamp, который удерживает значение в заданном диапазоне.

puts 15.clamp(0, 10)
puts (-5).clamp(0, 10)
puts 7.clamp(0, 10)

Сортировка сравнимых объектов

Поскольку <=> определён, массив ваших объектов можно отсортировать автоматически.

class Weight
  include Comparable
  attr_reader :grams
  def initialize(g); @grams = g; end
  def <=>(other); grams <=> other.grams; end
  def to_s; "#{grams}g"; end
end
list = [Weight.new(30), Weight.new(10), Weight.new(20)]
puts list.sort.map(&:to_s).inspect

Модулю перечисления нужен each

Enumerable требует определить each. Взамен Вы получаете map, select, reduce, min, max, sort и ещё десятки методов.

class TodoList
  include Enumerable
  def initialize(*items); @items = items; end
  def each(&block); @items.each(&block); end
end
list = TodoList.new("buy milk", "call mom")
puts list.map(&:upcase).inspect

Агрегация без дополнительных усилий

После добавления each становятся доступны методы агрегации, такие как count, min и include?.

class Scores
  include Enumerable
  def initialize(*n); @n = n; end
  def each(&block); @n.each(&block); end
end
s = Scores.new(8, 3, 9, 4)
puts s.max
puts s.min
puts s.count

select и reject

Вместе с ними становятся доступны и методы фильтрации.

class Numbers
  include Enumerable
  def initialize(*n); @n = n; end
  def each(&block); @n.each(&block); end
end
nums = Numbers.new(1, 2, 3, 4, 5, 6)
p nums.select(&:even?)
p nums.reject(&:even?)

reduce для подсчёта итогов

reduce (псевдоним inject) объединяет элементы, например складывает их.

class Basket
  include Enumerable
  def initialize(*p); @p = p; end
  def each(&block); @p.each(&block); end
end
b = Basket.new(10, 20, 30)
puts b.reduce(0) { |sum, price| sum + price }

Объединение обеих примесей

Добавьте Comparable для сортировки и Enumerable для итерации — и Ваш класс будет восприниматься как встроенная коллекция.

class Playlist
  include Enumerable
  def initialize(*songs); @songs = songs; end
  def each(&block); @songs.each(&block); end
end
pl = Playlist.new("c", "a", "b")
puts pl.sort.inspect
puts pl.first

Собираем всё вместе

Стандартные миксины позволяют обойтись минимальным контрактом:

  • Comparable: определите <=> и получите все операции сравнения.
  • Enumerable: определите each и получите полный набор инструментов для работы с коллекциями.
class Bag
  include Enumerable
  def initialize(*x); @x = x; end
  def each(&b); @x.each(&b); end
end
puts Bag.new(3, 1, 2).sort.inspect

Быстрая проверка

Проверьте, насколько хорошо Вы поняли стандартные миксины.

Повторение

Вы изучили стандартные миксины:

  • Comparable требует <=> и предоставляет сравнение, clamp и between?.
  • Enumerable требует each и предоставляет map, select, reduce, min, max и другие методы.
  • Вместе они делают пользовательские классы похожими на встроенные.
class Temp
  include Comparable
  attr_reader :deg
  def initialize(d); @deg = d; end
  def <=>(o); deg <=> o.deg; end
end
puts Temp.new(20) > Temp.new(15)

Часто задаваемые вопросы

Урок «Comparable и Enumerable» бесплатный?

Да — полный текст урока «Comparable и Enumerable» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Ruby Academy, подпишись на CoddyKit PRO. Курс Ruby Academy содержит 4 уроков всего.

Чему я научусь в уроке «Comparable и Enumerable»?

Стандартные примеси Ты практикуешь Ruby Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Ruby Academy?

Предыдущий опыт не требуется. Ruby Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «Comparable и Enumerable»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Ruby Academy?

Да. Каждый урок Ruby Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Определение модулей
  2. include и extend
  3. Comparable и Enumerable
  4. prepend и разрешение методов
← Назад к Ruby Academy