Menu
Coddy logo textTech

Duck Typing

Teil des Abschnitts Objektorientierte Programmierung der Ruby-Journey von Coddy. Lektion 33 von 57.

Ruby überprüft die Klasse eines Objekts nicht, bevor es eine Methode aufruft; es muss lediglich über die Methode verfügen. „Wenn es wie eine Ente läuft und wie eine Ente quakt, ist es eine Ente.“ Das ist Duck-Typing: Klassen, die keinen gemeinsamen Obertyp haben, können trotzdem an derselben Stelle verwendet werden:

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 }

Ausgabe:

Quack
Beep
...news...

Auch integrierte Klassen sind beteiligt. Eine Methode, die nur << verwendet, funktioniert mit einem Array, einem String oder jedem beliebigen Objekt von dir, das << definiert:

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).count

Ausgabe:

["1", "2"]
"12"
3

respond_to?(:name) fragt ab, ob ein Objekt über eine öffentliche Methode verfügt, ohne sie aufzurufen. Verwende es, wenn ein Objekt ein optionales Feature möglicherweise unterstützt oder nicht:

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
end

Ausgabe:

printing report
Scanner cannot print

Wenn das Objekt nicht über die Methode verfügt, löst der Aufruf einen NoMethodError aus, dessen Meldung die Methode und das Objekt nennt. Duck Typing beruht darauf, dass jedes übergebene Objekt auf die Methoden antwortet, die an es gesendet werden:

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
end

Ausgabe:

Meow
undefined method `speak' for an instance of Integer
challenge icon

Aufgabe

Einfach

Vervollständige die Klassen Printer und LineCounter sowie den Helfer export(items, target) in functions.rb. export sendet jedes Element mit target << item.to_s an das Ziel und gibt das Ziel zurück. Printer#<< gibt den Text mit einer Zeilennummer, 1: text, aus und gibt den Drucker zurück. LineCounter#<< zählt Zeilen und Zeichen und gibt den Zähler zurück; sein to_s gibt 3 lines, 12 chars zurück.

Der bereitgestellte Code liest Elemente ein, exportiert sie in ein Array (ausgegeben mit p), in einen neuen String (ausgegeben mit p), an einen Printer und an einen LineCounter (ausgegeben mit puts).

Dein Code gehört in printer.rb, line_counter.rb und functions.rb. main.rb enthält den bereitgestellten Eingabe-/Ausgabecode und kann nicht bearbeitet werden.

Probier es selbst

require_relative 'printer'
require_relative 'line_counter'
require_relative 'functions'

# Mitgelieferter Ein-/Ausgabecode: belasse ihn wie er ist
input = []
while (line = gets)
  input << line.chomp
end
p export(input, [])
p export(input, +"")
export(input, Printer.new)
puts export(input, LineCounter.new)
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung

Übe selbstständig: Online-Ruby-Compiler