Menu
Coddy logo textTech

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 pasuje do każdej liczby całkowitej, ponieważ case porównuje za pomocą ===, a Integer === 5 sprawdza, czy 5 jest typu 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 klas podrzędnych. 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

Jedno when może wymieniać kilka klas, a gałęzie mogą wykonywać rzeczywiste operacje na wartości, na przykład sumować zagnieżdżoną strukturę o mieszanych typach:

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 na podstawie 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:

# Twoje własne klasy: niech każda z nich odpowie
shape.area

# Wartości wbudowane pochodzące z zewnątrz: rozgałęź kod zależnie od 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 instrukcji 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 po konwersji za pomocą to_s), nothing dla nil oraz other Symbol dla każdej innej wartości. W testach jedynym innym rodzajem wartości są symbole.

Dostarczony kod zamienia każdą linię wejściową na wartość (liczbę całkowitą, liczbę dziesiętną, listę [a,b], nil, symbol :name lub tekst) i wypisuje wynik funkcji describe dla każdej z nich.

Umieść swój kod w pliku functions.rb. Plik 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