Условия в операторе case
не являются логическими выражениями;это значения, которые сравниваются с целевым объектом с помощью оператора ===
. Конечно, любой класс может переопределить этот оператор, но предопределенный возвращает true только для небольшого набора условий (например, is_a?
, равно, содержится в, =~
...). Наличие логического выражения в качестве условия when
не вызывает совпадения, если это выражение истинно;оно вызывает совпадение, когда целевой объект ===
имеет значение выражения, а для большинства объектов obj === true
само по себе не соответствует действительности.
Так что вы можете поменять case
на if
/ else
цепочка в этом случае:
if a.is_a? String
puts 'string'
elsif a.is_a?(Array) && a.all? { |obj| obj.is_a? String }
puts 'an array with only string classes'
else
raise ArgumentError, "unsupported object #{a}:#{a.class}"
end
Или выполнить вложенную проверку внутри условия дела. Но тогда у вас будет два else
состояния, одно для if
(что означает, что оно соответствует регистру массива, но не всех строк), и одно для case
(что означает, что это было что-то совсем другое). Поэтому вместо того, чтобы дублировать код обработки ошибок, подобный этому, я использовал логическую переменную, чтобы указать, когда ошибка должна быть raise
d:
ok = false
case a
when String
puts 'string'
ok = true
when Array
if a.all? { |obj| obj.is_a? String }
puts 'an array with only string classes'
ok = true
end
end
if !ok
raise ArgumentError, "unsupported object #{a}:#{a.class}"
end