Menu
Coddy logo textTech

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: Array

Como === 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.new

Salida:

a dog
some animal
not an animal
true

Un 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.5

La 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 ...
end
challenge icon

Desafío

Fácil

Completa 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)) }
quiz iconPonte a prueba

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

Practica por tu cuenta: Compilador de Ruby online