case y clases
Parte de la sección Programación orientada a objetos del Journey de Ruby de Coddy. Lección 35 de 57.
case puede bifurcar según la clase de un valor. when Integer coincide con cada entero, porque case compara con ===, y Integer === 5 pregunta si 5 es un 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) }Salida:
integer 5
float 2.50
text of 2 chars
nothing
other: ArrayComo === en una clase sigue a is_a?, un when con una superclase también coincide con sus subclases. Ordena las ramas desde la clase más específica hasta la más general:
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.newSalida:
a dog
some animal
not an animal
trueUn when puede enumerar varias clases, y las ramas pueden realizar un trabajo real con el valor, como totalizar una estructura anidada de tipos mixtos:
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] }])Salida:
10.5La ramificación según clases es adecuada para valores cuyas clases no puedes dotar de nuevos métodos, como números, cadenas y matrices, o para datos externos. Para tus propias clases, prefiere el polimorfismo: una clase nueva necesita después un método nuevo, no una rama nueva en cada case:
# tus propias clases: deja que cada una responda
shape.area
# valores incorporados de fuera: ramifica según la clase
case value
when Integer then ...
when String then ...
endDesafío
FácilCompleta el ayudante describe(value) en functions.rb con un case sobre la clase del valor. Devuelve integer 5 (odd) o integer 4 (even), float 2.50 con dos decimales, text "hi" (2 chars), list of 3: 1, a, 2.5 (los elementos unidos mediante to_s), nothing para nil y other Symbol para cualquier otra cosa. Los símbolos son el único otro tipo presente en las pruebas.
El código proporcionado convierte cada línea de entrada en un valor (números enteros, decimales, listas [a,b], nil, símbolos :name o texto) e imprime describe para cada uno.
Tu código debe ir en functions.rb. main.rb contiene el código proporcionado de entrada/salida y no se puede editar.
Pruébalo tú mismo
require_relative 'functions'
# Código de entrada/salida suministrado: déjalo tal 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 lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación orientada a objetos
1Clases y objetos
Trabajar con archivosDefinir clasesVariables de instanciaMétodos y selfto_s e inspectRepaso: tarjeta de biblioteca4Encapsulación
Métodos privadosMétodos protegidosAsignadores privadosProtección del estadoRepaso: máquina expendedora7Polimorfismo y tipado pato
PolimorfismoTipado patoMétodos abstractoscase y clasesRepaso: métodos de pago2Accesores y self
Lectores y escritoresSetters personalizadosself en los métodosIdentidad e igualdadRepaso: lista de contactos5Herencia
SubclasesSobrescritura de métodosLlamar a superis_a? y ancestrosRepaso - Nómina del personal8Métodos especiales
Igualdad y hashMétodos de operadoresIndexación y adiciónColecciones personalizadasRepaso: fracciones11Proyecto: Gestión de biblioteca
Libros y miembrosPréstamo de librosPractica por tu cuenta: Compilador de Ruby online