Vererbung
Einleitung
Als Programmierer ist man danach bestrebt, bereits vorhandenen Code wieder zu verwenden. Vererbung ist eine Möglichkeit dazu: Eine Klasse erbt die Methoden und Eigenschaften einer (oder mehreren - das ist in Perl der Fall) anderen Klasse. Die Klasse, von der man erbt nennt man Basisklasse und die Klasse, die erbt, nennt man abgeleitete Klasse. Es wird also bereits vorhandener Code verwendet. So könnte zum Beispiel eine Klasse Fortbewegungsmittel heißen. In dieser gibt es die Methode Geschwindigkeit, etc. Will man nun eine neue Klasse Auto programmieren, dann kann man diese von Fortbewegungsmittel ableiten und die vorhandenen Methoden (z. B. Geschwindigkeit) wieder verwenden. Auch eine Klasse Fahrrad kann von Fortbewegungsmittel abgeleitet werden.
Vererbung in Perl, @ISA
Vererbung in Perl ist nichts weiter als das Angeben, von Klassen (das sind die Basisklassen) in denen Perl nach der zu erbenden Methode sucht. Ist die Methode nicht in der aktuellen Klasse (das ist die abgeleitete Klasse) vorhanden, wird in den angebenen Basisklassen gesucht, bis die gesuchte Methode gefunden worden ist.
Eigenschaften werden nicht vererbt. Das umgeht man durch guten Programmierstil, indem man geeignete Konstruktoren schreibt und diese in der bzw. den Superklasse(n) aufruft.
Wie bereits erwähnt ist Vererbung nichts anderes als das Angeben der Klassen, von denen geerbt werden soll. Das macht man über das Array @ISA - was von "is a" kommt: ("Auto is a Fortbewegungsmittel").
Ein Beispiel: Die Klasse Auto erbt von Fortbewegungsmittel:
package Fortbewegungsmittel;
sub new () {
my $self=shift;
my $newInst={};
bless($newInst, $self);
$newInst->setzeGeschwindigkeit(0);
}
sub setzeGeschwindigkeit(){
my $self = shift;
$self->{Geschwindigkeit} = shift;
}
sub Geschwindigkeit(){
my $self = shift;
$self->{Geschwindigkeit};
}
1;
- Die Klasse Fortbewegungsmittel enthält neben dem Konstruktor new zwei weitere Methoden: setzeGeschwindigkeit und Geschwindigkeit
use Fortbewegungsmittel;
package Auto;
@ISA = qw( Fortbewegungsmittel );
sub new () {
my $self=shift;
my $newInst={};
bless($newInst, $self);
}
sub setzeVerbrauch() {
my $self=shift;
$self->{Verbrauch}=shift;
}
sub Verbrauch() {
my $self=shift;
$self->{Verbrauch};
}
1;
- Die Klasse Fortbewegungsmittel ist in die Klasse Auto eingebunden. Damit steht diese Klasse der Datei Auto.pm zur Verfügung.
- Die Klasse Auto erbt von der Klasse Fortbewegungsmittel. Das wird mit @ISA = qw( Fortbewegungsmittel ); erreicht. Damit ist Fortbewegungsmittel die Basisklasse von Auto. Letzteren stehen alle Methoden aus Fortbewegungsmittel zur Verfügung (Hier sei erstmal new außer Acht gelassen.).
- Es werden zwei neue Methoden hinzugefügt: setzeVerbrauch() und Verbrauch().
use Auto;
use Auto;
my $bmw = Auto->new();
$bmw->setzeVerbrauch(10);
$bmw->setzeGeschwindigkeit(220);
print "Verbrauch: ".$bmw->Verbrauch()."\n";
print "Geschwindigkeit: ".$bmw->Geschwindigkeit()."\n";
Verbrauch: 10
Geschwindigkeit: 220
- Mit $bmw = Auto->new() wird eine Instanz der Klasse Auto erzeugt.
- Dem $bmw stehen alle Methoden aus der Klasse Auto zur Verfügung; d. h., auch die Methoden der Basisklasse Fortbewegungsmittel.
Überschreiben von Methoden
Es kommt oft der Fall vor, dass in der Basisklasse und in der abgeleiteten Klasse dieselbe Funktion implementiert ist. Das nent man Überschreiben von der betroffenen Methode in der Basisklasse. Das Mittel des Überschreibens ist im Normalfall gewollt! Dazu folgendes Beispiel:
package Fortbewegungsmittel;
...
sub out() {
my $self = shift;
"Geschwindigkeit: ".$self->Geschwindigkeit()."\n";
}
1;
package Auto;
...
sub out() {
my $self = shift;
"Geschwindigkeit: ".$self->Geschwindigkeit()."\n".
"Verbrauch: ".$self->Verbrauch()."\n";
}
1;
- Die Methode out kommt in beiden Klassen vor. Deshalb wird in einer Instanz die Methode der abgeleiteten Klasse (Auto) benutzt.
- Das nennt man (im allgemeinen Sprachgebrauch) Überschreiben der Methode. In Perl bedeutet Überschreiben nur, dass nicht in der Basisklasse nach der Methode gesucht wird, weil diese bereits in der abgeleiteten Klasse existiert und deshalb als erstes gefunden wird.
Dazu folgender Code:
use Auto;
my $bmw = Auto->new();
$bmw->setzeVerbrauch(10);
$bmw->setzeGeschwindigkeit(220);
print $bmw->out();
Geschwindigkeit: 220
Verbrauch: 10
SUPER
Der Mangel der obigen Vorgehensweise: Die Ausgabe der Geschwindigkeit wurde doppelt programmiert. Diesen kann man beseitigen, indem man mit dem Schlüsselwort SUPER:: auf die Basisklasse zugreift:
package Auto;
...
sub out() {
my $self = shift;
$self->SUPER::out()."Verbrauch: ".$self->Verbrauch()."\n";
}
1;
- Mit Hilfe von SUPER:: kann direkt auf die Methoden der Basisklasse zugegriffen werden.
use Auto;
my $bmw = Auto->new();
$bmw->setzeVerbrauch(10);
$bmw->setzeGeschwindigkeit(220);
print $bmw->out();
Geschwindigkeit: 220
Verbrauch: 10