Menu
CoddyTech

case i klasy

Część sekcji Programowanie obiektowe ścieżki Ruby w Coddy. Lekcja 35 z 57.

case może wybierać gałąź na podstawie klasy wartości. when Integer dopasowuje każdą liczbę całkowitą, ponieważ case porównuje za pomocą ===, a Integer === 5 sprawdza, czy 5 jest obiektem 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) }

Wynik:

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

Ponieważ === dla klasy działa zgodnie z is_a?, instrukcja when z klasą nadrzędną pasuje również do jej podklas. Uporządkuj gałęzie od najbardziej szczegółowej klasy do najbardziej ogólnej:

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

Wynik:

a dog
some animal
not an animal
true

Jedna instrukcja when może wymieniać kilka klas, a poszczególne gałęzie mogą wykonywać na wartości konkretne operacje, na przykład sumować zagnieżdżoną strukturę zawierającą różne typy:

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

Wynik:

10.5

Rozgałęzianie według klas sprawdza się w przypadku wartości, którym nie możesz dodać nowych metod, takich jak liczby, ciągi znaków i tablice, lub danych z zewnątrz. W przypadku własnych klas preferuj polimorfizm: nowa klasa wymaga wtedy nowej metody, a nie nowej gałęzi w każdym case:

# własne klasy: niech każda odpowie sama
shape.area

# wbudowane wartości z zewnątrz: wybierz gałąź na podstawie klasy
case value
when Integer then ...
when String then ...
end
challenge icon

Wyzwanie

Łatwy

Uzupełnij funkcję pomocniczą describe(value) w pliku functions.rb, używając case dla klasy wartości. Zwraca ona integer 5 (odd) lub integer 4 (even), float 2.50 z dwoma miejscami po przecinku, text "hi" (2 chars), list of 3: 1, a, 2.5 (połączone elementy to_s), nothing dla nil i other Symbol dla wszystkiego innego. Symbole to jedyny inny rodzaj wartości w testach.

Dostarczony kod zamienia każdą linię wejściową na wartość (liczby całkowite, liczby dziesiętne, listy [a,b], nil, symbole :name lub tekst) i wypisuje wynik describe dla każdej z nich.

Twój kod umieść w pliku functions.rb. main.rb zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.

Spróbuj swoich sił

require_relative 'functions'

# Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
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 iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator Ruby online