case и классы
Часть раздела Объектно-ориентированное программирование путешествия по Ruby на Coddy. Урок 35 из 57.
case может выполнять ветвление по классу значения. when Integer сопоставляется с каждым целым числом, поскольку case сравнивает с помощью ===, а Integer === 5 проверяет, является ли 5 объектом типа Integer (is_a?):
def describe(value)
case value
when Integer then "integer #{value}"
when Float then format("float %.2f", value)
when String then "text of #{value.size} chars"
when nil then "nothing"
else "other: #{value.class}"
end
end
[5, 2.5, "hi", nil, [1, 2]].each { |v| puts describe(v) }Вывод:
integer 5
float 2.50
text of 2 chars
nothing
other: ArrayПоскольку === для класса следует поведению is_a?, конструкция when с суперклассом также соответствует его подклассам. Расположи ветви от наиболее конкретного класса к наиболее общему:
class Animal
end
class Dog < Animal
end
def kind(x)
case x
when Dog then "a dog"
when Animal then "some animal"
else "not an animal"
end
end
puts kind(Dog.new)
puts kind(Animal.new)
puts kind("Rex")
puts Animal === Dog.newВывод:
a dog
some animal
not an animal
trueОдин when может перечислять несколько классов, а ветви могут выполнять реальные действия со значением, например подсчитывать сумму вложенной структуры со смешанными типами:
def total(value)
case value
when Integer, Float then value
when String then value.to_f
when Array then value.sum { |v| total(v) }
when Hash then total(value.values)
else 0
end
end
puts total([1, "2.5", { a: 3, b: [4, nil] }])Вывод:
10.5Ветвление по классам подходит для значений, классам которых нельзя добавить новые методы, например для чисел, строк и массивов, а также для данных извне. Для собственных классов предпочитайте полиморфизм: новому классу тогда нужен новый метод, а не новая ветвь в каждом case:
# ваши собственные классы: пусть каждый отвечает
shape.area
# встроенные значения извне: ветвление по классу
case value
when Integer then ...
when String then ...
endЗадание
ЛегкоЗавершите вспомогательную функцию describe(value) в functions.rb, используя case для определения класса значения. Она возвращает integer 5 (odd) или integer 4 (even), float 2.50 с двумя знаками после запятой, text "hi" (2 chars), list of 3: 1, a, 2.5 (элементы объединяются после вызова to_s), nothing для nil и other Symbol для всего остального. В тестах единственным другим типом являются символы.
Предоставленный код преобразует каждую входную строку в значение (целые числа, десятичные числа, списки [a,b], nil, символы :name или текст) и выводит результат работы describe для каждой строки.
Ваш код должен находиться в functions.rb. В main.rb содержится предоставленный код ввода/вывода, и его нельзя редактировать.
Попробуйте сами
require_relative 'functions'
# Предоставленный код ввода/вывода: оставьте его как есть
input = []
while (line = gets)
input << line.chomp
end
def parse(text)
return Integer(text) if text.match?(/\A-?\d+\z/)
return Float(text) if text.match?(/\A-?\d+\.\d+\z/)
return nil if text == "nil"
return text[1..].to_sym if text.start_with?(":")
return text[1...-1].split(",").map { |t| parse(t) } if text.start_with?("[")
text
end
input.each { |line| puts describe(parse(line)) }
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Классы и объекты
Работа с файламиОпределение классовПеременные экземпляраМетоды и selfto_s и inspectПовторение — читательский билет4Инкапсуляция
Приватные методыЗащищённые методыПриватные сеттерыЗащита состоянияПовторение — торговый автомат7Полиморфизм и утиная типизация
ПолиморфизмУтиная типизацияАбстрактные методыcase и классыПовторение — способы оплаты10Шаблоны проектирования, часть 2
Делегирование с помощью ForwardableШаблон декоратораШаблон строителяШаблон состояния2Аксессоры и self
Чтение и записьПользовательские сеттерыself в методахИдентичность и равенствоПовторение — список контактов5Наследование
ПодклассыПереопределение методовВызов superis_a? и предкиПовторение — расчёт зарплаты сотрудников8Специальные методы
Равенство и хешированиеМетоды операторовИндексация и добавлениеПользовательские коллекцииПовторение — дроби11Проект: Управление библиотекой
Книги и читателиВыдача книг3Методы и переменные классов
Методы классовПеременные экземпляра классаКонстантыФабричные методыПовторение — коды купонов6Модули и примеси
Модули и includeРасширение объектовМодуль ComparableМодуль EnumerableПовторение — спортивная лига9Паттерны проектирования. Часть 1
Паттерн «Одиночка»Фабричный паттернПаттерн «Наблюдатель»Паттерн «Стратегия»Потренируйтесь самостоятельно: Онлайн-компилятор Ruby