Ruby-Programmierung: Vererbung
Zurück zum Inhaltsverzeichnis.
Stellen Sie sich einen Baum vor. Er hat einen Stamm, Wurzeln und eine Krone. Betrachtet man nun jedoch zwei konkrete Bäume, z.B. Tanne und Birke, so zeigen sich Unterschiede in der Farbe des Stammes, der eine hat Blätter, der andere Nadeln und so weiter. Unser Verständnis von der Welt ist offensichtlich hierarchischer Art - zwar teilen alle Bäume die Eigenschaften von Bäumen, können sich aber in ihrer konkreten Ausprägung unterscheiden.
Diese hierarchische Form bei der Beschreibung der Welt findet man ebenfalls in objektorientierten Sprachen wieder. Durch Vererbung werden Eltern-Kind-Relationen zwischen den Klassen definiert, die es erlauben, das oben genannte Beispiel zu modellieren.
Vererbung
BearbeitenGehen wir in diesem Beispiel noch eine Stufe höher und erstellen eine Klasse Plant
, von der wir konkrete Pflanzen, wie Bäume, ableiten wollen.
class Plant
def initialize(name)
@name = name
end
end
Vererbung erfolgt mittels eines <
. Dabei übernimmt die erbende Klasse alle Variablen und Methoden der Elternklasse.
class Tree < Plant
def initialize(name)
super(name)
@has_trunk = true
end
end
super
ruft die gleichnamige Methode der Elternklasse auf und erlaubt es, dass sich eine Veränderung der Methoden der Elternklasse auch auf die Kinder vererbt, anstatt sie zu überschreiben.
Mehrfachvererbung/Mixins
BearbeitenMehrfachvererbung beschreibt die Möglichkeit, dass eine Klasse Eigenschaften von mehreren Elternklassen erbt. Ruby kennt keine direkte Mehrfachvererbung, sondern ermöglicht ein ähnliches Verhalten mit Mixins.
Mixins sind Module, die zu Klassen hinzugefügt werden und so diese Klassen um Funktionalität erweitern. Sie dienen meist dazu abstrakte Methoden bereitzustellen, die in mehreren Klassen sinnvoll angewendet werden können. Beispielsweise kann ein Baum wachsen, genauso wie ein Tier. Man könnte argumentieren, dass man ein gemeinsames Elternobjekt einfügen könnte (Lebewesen), das diese Methode bereitstellt, doch gibt es oft nicht diese einfache Möglichkeit neue Elternobjekte einzufügen.
module Growable
def grow!
@height ||= 0
@velocity ||= 0.1
@height += @velocity
self
end
end
class Tree
attr_reader :height
include Growable
end
puts Tree.new("Birch").grow!.grow!.height
In diesem Beispiel wird die Klasse Tree
durch eine grow!
-Methode erweitert. Dadurch ist es möglich, den selben Code auch in anderen Klassen zu verwenden, die gegebenenfalls unterschiedliche Elternklassen haben.
Hier zeigt sich auch der Unterschied zwischen den verschiedenen Möglichkeiten des letzten Kapitels Methoden auf Modulen zu definieren. Eine mit module_function
definierte Modulmethode wird nicht der Objektinstanz hinzugefügt, kann aber innerhalb der Klasse ohne Modulprefix aufgerufen werden, im Gegensatz zu den anderen beiden aufgezeigten Varianten, die den Aufruf nur über den Modulnamen erlauben. Instanzmethoden werden wie oben gezeigt der Objektinstanz hinzugefügt.