Polymorphismus
Teil des Abschnitts Objektorientierte Programmierung der Ruby-Journey von Coddy. Lektion 32 von 57.
Polymorphismus bedeutet, dass ein Methodenaufruf mit Objekten verschiedener Klassen funktioniert und jedes Objekt auf seine eigene Weise antwortet. Code, der eine Schleife über Formen ausführt, ruft für jede area auf, ohne zu fragen, um welche Art von Form es sich handelt:
class Shape
def to_s
format("%s %.2f", self.class.name.downcase, area)
end
end
class Circle < Shape
def initialize(r)
@r = r
end
def area
3.14159 * @r * @r
end
end
class Square < Shape
def initialize(side)
@side = side
end
def area
@side * @side
end
end
shapes = [Circle.new(1), Square.new(3)]
shapes.each { |s| puts s }
puts format("total %.2f", shapes.sum(&:area))Ausgabe:
circle 3.14
square 9.00
total 12.14Ohne Polymorphie muss der Aufrufer die Art jedes Objekts prüfen und diese Prüfung überall dort wiederholen, wo der Unterschied relevant ist. Mit Polymorphie liegt der Unterschied innerhalb jeder Klasse:
# ohne Polymorphismus
case shape.kind
when "circle" then 3.14159 * shape.r ** 2
when "square" then shape.side ** 2
end
# mit Polymorphismus
shape.areaDas Hinzufügen einer neuen Art von Objekt erfordert dann keine Änderung am aufrufenden Code: Eine neue Unterklasse mit ihrer eigenen area-Methode funktioniert in jeder bereits vorhandenen Schleife:
class Shape
def describe
"area #{area}"
end
end
class Square < Shape
def area
4
end
end
class Triangle < Shape
def area
6
end
end
[Square.new, Triangle.new].each { |s| puts s.describe }Ausgabe:
area 4
area 6to_s ist das alltägliche Beispiel: puts ruft es für jedes Objekt auf, und jede Klasse antwortet anders. Deine Klassen machen mit, indem sie ihr eigenes to_s definieren:
class Coin
def to_s
"a coin"
end
end
[42, "text", nil, [1, 2], Coin.new].each { |x| puts "[#{x}]" }Ausgabe:
[42]
[text]
[]
[[1, 2]]
[a coin]Aufgabe
EinfachVervollständige die Formen. Shape#to_s gibt circle: 3.14 zurück, den Klassennamen in Kleinbuchstaben und die Fläche mit zwei Dezimalstellen, und jede Unterklasse stellt area bereit: Circle.new(r) (verwende 3.14159 für Pi), Rectangle.new(w, h) und Triangle.new(base, height).
Der bereitgestellte Code liest Zeilen wie circle 1, rectangle 2 3 oder triangle 4 5, gibt jede Form aus, danach total: 22.14 und largest: rectangle: 6.00, und arbeitet ausschließlich mit to_s und area.
Dein Code gehört in shape.rb, circle.rb, rectangle.rb und triangle.rb. main.rb enthält den bereitgestellten Eingabe-/Ausgabecode und darf nicht bearbeitet werden.
Probier es selbst
require_relative 'shape'
require_relative 'circle'
require_relative 'rectangle'
require_relative 'triangle'
# Gelieferter Ein-/Ausgabe-Code: belasse ihn wie er ist
input = []
while (line = gets)
input << line.chomp
end
kinds = { "circle" => Circle, "rectangle" => Rectangle, "triangle" => Triangle }
shapes = input.map do |line|
kind, *numbers = line.split
kinds[kind].new(*numbers.map(&:to_f))
end
shapes.each { |s| puts s }
puts format("total: %.2f", shapes.sum(&:area))
puts "largest: #{shapes.max_by(&:area)}"
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Klassen und Objekte
Arbeiten mit DateienKlassen definierenInstanzvariablenMethoden und selfto_s und inspectRückblick – Bibliotheksausweis4Kapselung
Private MethodenGeschützte MethodenPrivate SetterZustand schützenRückblick – Verkaufsautomat7Polymorphismus und Duck Typing
PolymorphismusDuck TypingAbstrakte MethodenFälle und KlassenRückblick – Zahlungsmethoden2Getter und Setter sowie self
Leser und SchreiberBenutzerdefinierte Setterself in MethodenIdentität und GleichheitWiederholung – Kontaktliste5Vererbung
UnterklassenMethoden überschreibensuper aufrufenis_a? und VorfahrenRückblick – Gehaltsabrechnung des Personals8Spezielle Methoden
Gleichheit und HashOperator-MethodenIndexieren und AnhängenBenutzerdefinierte CollectionsRückblick – Brüche11Projekt: Bibliotheksverwaltung
Bücher und MitgliederBücher ausleihenÜbe selbstständig: Online-Ruby-Compiler