Menu
Coddy logo textTech

case e classi

Fa parte della sezione Programmazione orientata agli oggetti del percorso Ruby di Coddy. Lezione 35 di 57.

case può diramarsi in base alla classe di un valore. when Integer corrisponde a ogni numero intero, perché case confronta usando ===, e Integer === 5 verifica se 5 è 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) }

Output:

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

Poiché === su una classe segue is_a?, un when con una superclasse corrisponde anche alle sue sottoclassi. Ordina i rami dalla classe più specifica a quella più generale:

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

Output:

a dog
some animal
not an animal
true

Un when può elencare diverse classi e i rami possono svolgere operazioni effettive sul valore, come calcolare il totale di una struttura annidata di tipi misti:

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

Output:

10.5

La diramazione in base alle classi è adatta ai valori alle cui classi non puoi aggiungere nuovi metodi, come numeri, stringhe e array, o ai dati provenienti dall'esterno. Per le tue classi, preferisci il polimorfismo: una nuova classe richiede quindi un nuovo metodo, non una nuova diramazione in ogni case:

# le tue classi: lascia che ciascuna risponda
shape.area

# valori predefiniti provenienti dall'esterno: scegli in base alla classe
case value
when Integer then ...
when String then ...
end
challenge icon

Sfida

Facile

Completa l'helper describe(value) in functions.rb con un case sulla classe del valore. Restituisce integer 5 (odd) oppure integer 4 (even), float 2.50 con due decimali, text "hi" (2 chars), list of 3: 1, a, 2.5 (gli elementi uniti tramite to_s), nothing per nil e other Symbol per qualsiasi altro valore. Nei test, i simboli sono l'unico altro tipo.

Il codice fornito trasforma ogni riga di input in un valore (numeri interi, decimali, liste [a,b], nil, simboli :name o testo) e stampa describe per ciascuno.

Il tuo codice va in functions.rb. main.rb contiene il codice fornito per l'input/output e non può essere modificato.

Provalo tu

require_relative 'functions'

# Codice di input/output fornito: lascialo così com'è
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 iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore Ruby online