case e Classes
Parte da seção Programação orientada a objetos do Journey de Ruby da Coddy. Lição 35 de 57.
case pode ramificar com base na classe de um valor. when Integer corresponde a todo número inteiro, porque case compara usando ===, e Integer === 5 verifica se 5 é um 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) }Saída:
integer 5
float 2.50
text of 2 chars
nothing
other: ArrayComo === em uma classe segue is_a?, um when com uma superclasse também corresponde às suas subclasses. Ordene os ramos da classe mais específica para a mais geral:
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.newSaída:
a dog
some animal
not an animal
trueUm when pode listar várias classes, e os ramos podem realizar um trabalho real com o valor, como totalizar uma estrutura aninhada de tipos mistos:
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] }])Saída:
10.5A ramificação por classes é adequada para valores cujas classes você não pode dotar de novos métodos, como números, strings e arrays, ou para dados externos. Para suas próprias classes, prefira o polimorfismo: uma nova classe então precisa de um novo método, não de uma nova ramificação em cada case:
# suas próprias classes: deixe cada uma responder
shape.area
# valores embutidos de fora: ramifique na classe
case value
when Integer then ...
when String then ...
endDesafio
FácilComplete o auxiliar describe(value) em functions.rb com um case sobre a classe do valor. Ele retorna integer 5 (odd) ou integer 4 (even), float 2.50 com duas casas decimais, text "hi" (2 chars), list of 3: 1, a, 2.5 (os elementos unidos usando to_s), nothing para nil e other Symbol para qualquer outra coisa. Símbolos são o único outro tipo nos testes.
O código fornecido transforma cada linha de entrada em um valor (números inteiros, números decimais, listas [a,b], nil, símbolos :name ou texto) e imprime describe para cada um.
Seu código deve ficar em functions.rb. main.rb contém o código fornecido de entrada/saída e não pode ser editado.
Experimente você mesmo
require_relative 'functions'
# Código de entrada/saída fornecido: mantenha-o como está
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)) }
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação orientada a objetos
1Classes e Objetos
Trabalhando com ArquivosDefinindo ClassesVariáveis de InstânciaMétodos e selfto_s e inspectRevisão - Cartão da Biblioteca4Encapsulamento
Métodos privadosMétodos protegidosSetters privadosProtegendo o estadoRevisão - Máquina de venda automática7Polimorfismo e Duck Typing
PolimorfismoDuck TypingMétodos Abstratoscase e ClassesRevisão - Métodos de Pagamento2Acessores e self
Leitores e GravadoresSetters Personalizadosself nos MétodosIdentidade e IgualdadeRecapitulação - Lista de Contatos5Herança
SubclassesSobrescrita de métodosChamando superis_a? e ancestraisRevisão - Folha de pagamento da equipe8Métodos Especiais
Igualdade e hashMétodos de OperadoresIndexação e AdiçãoColeções PersonalizadasRevisão - Frações11Projeto: Gerenciamento de Biblioteca
Livros e MembrosEmpréstimo de LivrosPratique por conta própria: Compilador de Ruby online