Menu
CoddyTech

Cas et classes

Fait partie de la section Programmation orientée objet du Journey Ruby de Coddy. Leçon 35 sur 57.

case peut effectuer un branchement selon la classe d’une valeur. when Integer correspond à tous les entiers, car case compare avec ===, et Integer === 5 demande si 5 est 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) }

Résultat :

integer 5
float 2.50
text of 2 chars
nothing
other: Array

Comme === sur une classe suit is_a?, un when avec une superclasse correspond aussi à ses sous-classes. Ordonne les branches de la classe la plus spécifique à la plus générale :

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

Résultat :

a dog
some animal
not an animal
true

Un when peut lister plusieurs classes, et les branches peuvent effectuer un véritable travail avec la valeur, comme calculer le total d’une structure imbriquée de types mixtes :

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] }])

Sortie :

10.5

Le branchement selon les classes convient aux valeurs dont vous ne pouvez pas ajouter de nouvelles méthodes, comme les nombres, les chaînes et les tableaux, ou les données provenant de l’extérieur. Pour vos propres classes, privilégiez le polymorphisme : une nouvelle classe nécessite alors une nouvelle méthode, et non une nouvelle branche dans chaque case :

# vos propres classes : laissez chacune répondre
shape.area

# valeurs prédéfinies provenant de l’extérieur : choisissez une branche selon la classe
case value
when Integer then ...
when String then ...
end
challenge icon

Défi

Facile

Complète l'assistant describe(value) dans functions.rb avec un case portant sur la classe de la valeur. Il renvoie integer 5 (odd) ou integer 4 (even), float 2.50 avec deux décimales, text "hi" (2 chars), list of 3: 1, a, 2.5 (les éléments joints après application de to_s), nothing pour nil et other Symbol pour toute autre valeur. Les symboles sont le seul autre type présent dans les tests.

Le code fourni transforme chaque ligne d'entrée en une valeur (nombres entiers, nombres décimaux, listes [a,b], nil, symboles :name ou texte) et affiche le résultat de describe pour chacune.

Ton code va dans functions.rb. main.rb contient le code d'entrée/sortie fourni et ne peut pas être modifié.

Essayez vous-même

require_relative 'functions'

# Code d’entrée/sortie fourni : conservez-le tel quel
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 iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation orientée objet

Entraînez-vous par vous-même : Compilateur Ruby en ligne