Ключевое слово case в руби используется, когда надо выбрать какое-то одно из действий в зависимости от значения, которое лежит в какой-то переменной. Грубо описать его работу можно так:
case что_то
when значение1
# если что-то == значение1, идем сюда
when значение2
# если что-то == значение2, идем сюда
when значение3
# если что-то == значение3, идем сюда
...
else
# если никуда выше не зашли, идем сюда
end
# Продолжаем выполнять код
В языках программирования C/C++, C#, Java есть конструкция switch, которая выполняет похожую функцию.
Более жизненный пример. Напишем код, который выводит комментарий по оценке ученика. Сначала с помощью if-elsif-end
:
puts "Что получили сегодня за урок?"
mark = gets.to_i
if mark == 2
puts "Это неуд"
elsif mark == 3
puts "Удовлетворительно"
elsif mark == 4
puts "Хорошо"
elsif mark == 5
puts "Отлично!"
end
Аналогичный код с использованием case
будет выглядеть так:
puts "Что получили сегодня за урок?"
mark = gets.to_i
case mark
when 2
puts "Это неуд"
when 3
puts "Удовлетворительно"
when 4
puts "Хорошо"
when 5
puts "Отлично!"
end
Код становится проще за счет того, что не надо для каждой ветки писать mark ==
. Это хорошо.
В примере выше, если mark
не совпадет ни с одним из значений, программа вообще ничего не выведет. Если надо обработать случай, когда в переменной лежит что-то, что не попадает ни под один из случаев, можно написать else
после всех when
:
puts "Что получили сегодня за урок?"
mark = gets.to_i
case mark
when 2
puts "Это неуд"
when 3
puts "Удовлетворительно"
when 4
puts "Хорошо"
when 5
puts "Отлично!"
else
puts "Странная оценка"
end
Представим, что нам не важно, четверка у нас или пятерка. Нам и то и то — «отлично» (как это часто бывает), тогда эти значения можно указать через запятую:
puts "Что получили сегодня за урок?"
mark = gets.to_i
case mark
when 2
puts "Это неуд"
when 3
puts "Удовлетворительно"
when 4, 5
puts "Отлично!"
else
puts "Странная оценка"
end
Если mark
равен 4 или 5, то программа выведет на экран Отлично!
. Удобно! За это мы и любим руби.
Вместо одного значения (или нескольких значений через запятую), можно указать диапазон чисел с помощью объекта класса Range
, например, (3..5)
.
puts "Что получили сегодня за урок?"
mark = gets.to_i
case mark
when 2
puts "Придется пересдавать"
when (3..5)
puts "Покатит"
else
puts "Странная оценка"
end
Если mark
попадает в диапазон от 3 до 5 (включительно), программа напишет Покатит
. Тоже очень удобно.
Если, как в нашем случае, действие для каждого случая умещается в 1 строчку, можно записать это всё короче с помощью ключевого слова then
(англ. «тогда»):
puts "Что получили сегодня за урок?"
mark = gets.to_i
case mark
when 2 then puts "Придется пересдавать"
when (3..5) then puts "Покатит"
else
puts "Странная оценка"
end
Ключевое слово then
вставляется между значением и действием, которое в случае равенства этому значению нужно выполнить. Тут как бы можно прочитать:
А что у нас лежит в mark?
Если 2, тогда выведи "Придется пересдавать".
Если от 3 до 5, тогда выведи "Покатит".
Если что-то другое, выведи "Странная оценка".
Обратите внимание, что после else
нельзя поставить then
и принято писать действие на следующей строчке.
Во всех примерах у нас стоит просто переменная mark
. Но после case
может быть любое выражение:
case 2 + 2
when 4 then puts "Правильно"
when 5 then puts "Странновато"
end
Формально, в руби можно использовать case
даже без выражения:
case
when mark > 0 then puts "Оценка больше нуля"
when mark < 0 then puts "Оценка меньше нуля"
else
puts "Ну, я даже не знаю"
end
Но такая практика не считается очень удачной. Лучше так не делать.
Руби очень гибкий язык. Одно и то же поведение можно получить разными способами.
Оператор case
лучше всего применять именно когда у вас есть одна переменная (или выражение), которое определяет много принципиально разных сценариев развития программы.
Если же вам просто надо вывести нужную строку в зависимости от числа (как у нас в первом примере), лучше использовать хэш:
mark_names = {
2 => "Это неуд",
3 => "Удовлетворительно",
4 => "Хорошо",
5 => "Отлично!"
}
puts "Что получили сегодня за урок?"
mark = gets.to_i
puts mark_names[mark]
Однако, если захотим добавить одну строку для нескольких значений, указать диапазон чисел или условие else
, будет уже сложнее и придется придумывать что-то ещё.
* — для любознательных
На самом деле в руби case
внутри себя вызывает оператор ===
(«триравно», на англ. “threequal”) на указанном после слова when
объекте, передавая ему в качестве аргумента указанный после слова case
объект. Если интересно, можете прочитать про это в официальной документации.
Пользуйтесь case
с умом!