Menu
CoddyTech

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; das Objekt muss lediglich über die Methode verfügen. „Wenn es läuft wie eine Ente und quakt wie eine Ente, ist es eine Ente.“ Das ist Duck-Typing: Klassen ohne gemeinsame Oberklasse 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 machen mit. Eine Methode, die nur << verwendet, funktioniert mit einem Array, einem String oder einem 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 eine öffentliche Methode besitzt, ohne sie aufzurufen. Verwende es, wenn ein Objekt ein optionales Feature möglicherweise unterstützt oder auch 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 die Methode nicht hat, löst der Aufruf NoMethodError aus, dessen Meldung die Methode und das Objekt nennt. Duck-Typisierung 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 aus, 1: text, 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 und 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 Ein-/Ausgabecode und kann nicht bearbeitet werden.

Probier es selbst

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

# Bereitgestellter Eingabe-/Ausgabecode: unverändert lassen
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