Typowanie kacze
Część sekcji Programowanie obiektowe ścieżki Ruby w Coddy. Lekcja 33 z 57.
Ruby nie sprawdza klasy obiektu przed wywołaniem metody; obiekt musi jedynie mieć tę metodę. „Jeśli chodzi jak kaczka i kwacze jak kaczka, to jest kaczką”. To typowanie kacze: klasy, które nie mają wspólnej nadklasy, nadal mogą być używane w tym samym miejscu:
class Duck
def speak
"Quack"
end
end
class Robot
def speak
"Beep"
end
end
class Radio
def speak
"...news..."
end
end
[Duck.new, Robot.new, Radio.new].each { |thing| puts thing.speak }Wynik:
Quack
Beep
...news...Wbudowane klasy również biorą w tym udział. Metoda, która używa tylko <<, działa z tablicą, ciągiem znaków lub dowolnym obiektem, który zdefiniujesz i który ma zdefiniowane <<:
class Tally
attr_reader :count
def initialize
@count = 0
end
def <<(_item)
@count += 1
self
end
end
def export(items, target)
items.each { |item| target << item.to_s }
target
end
p export([1, 2], [])
p export([1, 2], +"")
puts export([1, 2, 3], Tally.new).countWynik:
["1", "2"]
"12"
3respond_to?(:name) sprawdza, czy obiekt ma publiczną metodę, nie wywołując jej. Używaj go, gdy obiekt może obsługiwać opcjonalną funkcję lub nie:
class Printer
def print_page(text)
"printing #{text}"
end
end
class Scanner
end
[Printer.new, Scanner.new].each do |device|
if device.respond_to?(:print_page)
puts device.print_page("report")
else
puts "#{device.class} cannot print"
end
endWynik:
printing report
Scanner cannot printGdy obiekt nie ma danej metody, wywołanie powoduje błąd NoMethodError, którego komunikat wskazuje nazwę metody i obiektu. Duck typing opiera się na tym, że każdy przekazany obiekt odpowiada na wysyłane do niego metody:
def loudest(things)
things.map(&:speak).max_by(&:size)
end
class Cat
def speak
"Meow"
end
end
puts loudest([Cat.new, Cat.new])
begin
loudest([Cat.new, 42])
rescue NoMethodError => e
puts e.message
endWynik:
Meow
undefined method `speak' for an instance of IntegerWyzwanie
ŁatwyUzupełnij klasy Printer i LineCounter oraz funkcję pomocniczą export(items, target) w pliku functions.rb. export wysyła każdy element do celu za pomocą target << item.to_s i zwraca cel. Printer#<< wypisuje tekst z numerem wiersza w formacie 1: text i zwraca drukarkę. LineCounter#<< zlicza wiersze i znaki oraz zwraca licznik; jego metoda to_s zwraca 3 lines, 12 chars.
Dostarczony kod odczytuje elementy i eksportuje je do tablicy (wypisywanej za pomocą p), do nowego ciągu znaków (wypisywanego za pomocą p), do obiektu Printer oraz do obiektu LineCounter (wypisywanego za pomocą puts).
Twój kod umieść w plikach printer.rb, line_counter.rb i functions.rb. Plik main.rb zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.
Spróbuj swoich sił
require_relative 'printer'
require_relative 'line_counter'
require_relative 'functions'
# Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
input = []
while (line = gets)
input << line.chomp
end
p export(input, [])
p export(input, +"")
export(input, Printer.new)
puts export(input, LineCounter.new)
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Klasy i obiekty
Praca z plikamiDefiniowanie klasZmienne instancjiMetody i selfto_s i inspectPowtórzenie – karta biblioteczna4Hermetyzacja
Metody prywatneMetody chronionePrywatne setteryOchrona stanuPowtórzenie – automat vendingowy7Polimorfizm i typowanie kacze
PolimorfizmTypowanie kaczeMetody abstrakcyjnecase i klasyPowtórzenie – metody płatności10Wzorce projektowe, część 2
Delegowanie z ForwardableWzorzec dekoratoraWzorzec budowniczegoWzorzec stanu2Metody dostępowe i self
Gettery i setteryWłasne setteryself w metodachTożsamość i równośćPowtórzenie – lista kontaktów5Dziedziczenie
PodklasyNadpisywanie metodWywoływanie superis_a? i przodkowiePowtórka – lista płac pracowników8Metody specjalne
Równość i hashMetody operatorówIndeksowanie i dodawanieWłasne kolekcjePowtórka – ułamki11Projekt: Zarządzanie biblioteką
Książki i czytelnicyWypożyczanie książekPoćwicz samodzielnie: Kompilator Ruby online