Realisierung eines Objekts in PerlPerl

SeitenanfangSeitenendeKlasse, Package und Modul

Für Realisierung einer Klasse braucht man einen Namensraum (das ist der Name der Klasse z. B. CGI). Zudem ist es sinnvoll eine Klasse für sich in eine Datei (wieder mit dem gleichen Namen und der Endung pm) zu schreiben. Damit haben wir schon die äußere Umgebung für eine Klasse unter Perl geschaffen: Ein Modul (z. B. Klassenname.pm) mit einem Namensraum (z. B. Klassenname). Der Name des Moduls und des Packagee sollten übereinstimmen.

Ein noch nicht komplettes Beispiel für eine CGI-Klasse: smallCGI:

# smallCGI.pm
package smallCGI;

1;

SeitenanfangSeitenendeKonstruktor

Für den Konstruktor kann man im Gegensatz zu anderen Programmiersprachen einen beliebigen Namen auswählen. Es hat sich jedoch der Name new für die Funktion des Konstruktors eingebürgert.

Eine Instanz einer Klasse wird wie folgt erzeugt:

# t.pl
use smallCGI;

my $perli=smallCGI->new();

Die zugehörige Klasse sieht so aus:

#Klasse smallCGI
package smallCGI;

sub new {
  my $self=shift;
  my $ref={};

  bless($ref, $self);  # nicht &bless schreiben!
  $ref;
}

1;

new liefert eine Referenz zurück, die an eine Klasse (Modul) gebunden ist. Damit weiß das Objekt $perli, zu welcher Klasse es gehört. Die hier angegebenen Schritte in der Funktion new sind notwendig. new kann aber auch ergänzt werden.

# t.pl
use smallCGI;

my $perli2={};
print $perli2."\n";

my $perli=smallCGI->new();
print $perli."\n";
HASH(0x1a6f0f0)
smallCGI=HASH(0x1a6f1a4)
Eine Instanz einer Klasse ist somit ein Hash, der weiß zu welcher Klasse er gehört.

SeitenanfangSeitenendeDestruktor

Perl zerstört die Instanzen einer Klasse von selbst. Um jedoch besondere Aktivitäten vor dem Zerstören auszuführen, gibt es die "Destruktor-Funktion" DESTROY. Im Gegensatz zu new ist dieser Name festgelegt.

Besondere Aktivitäten sind zum Beispiel ein geöffnetes File oder eine geöffnete Datenbankanbindung schließen. Wird nämlich zu einer konkreten Instanz eine Datei geöffnet, sollte diese auch wieder geschlossen werden, bevor die Instanz zerstört wird.

Damit können wir jetzt eine konkrete Instanz eines Objekts erzeugen und zerstören (lassen). Jedoch hat diese Instanz weder irgendwelche Eigenschaften noch Methoden (außer new).

SeitenanfangSeitenendeMethoden

Methoden sind Funktionen, die zu einem Objekt gehören. Das heißt, sie sind in der zugehörigen Klasse definiert und können von der Instanz benutzt werden. Genauso wie bei new wird auch bei jeder anderen Methode ein erstes Argument "automatisch" übergeben. Der Unterschied dazu: Das erste Argument ist nicht der Klassenname, sondern die Referenz auf den in new erzeugten Hash - also die aktuelle Instanz. Als nächstes können weitere Argumente folgen.

Hier die Erweiterung obiger Klasse um drei Methoden:

#Klasse smallCGI
package smallCGI;

sub new {
  my $self=shift;
  my $ref={};

  bless($ref, $self); # nicht &bless schreiben!
  $ref;
}

sub printHead {
  my $self=shift;
  print "<html>\n<head>\n</head>\n<body>\n";
}

sub printParagraph {
  my $self=shift;
  my $text=shift;
  print "\n<p>\n";
  print $text;
  print "\n</p>\n";
}

sub printEnd {
  my $self=shift;
  print "\n</body>\n</html>\n";
}

1;

Das fällt auf:

Der Code des Hauptprogramm sieht z. B. so aus:

# t.pl
use smallCGI;

my $perli=smallCGI->new;

$perli->printHead;
$perli->printParagraph("A simple dynamic HTML-page.\nIt's nice ...");
$perli->printEnd;

Das fällt auf:

Die Ausgabe:

<html>
<head>
</head>
<body>

<p>
A simple dynamic HTML-page.
It's nice ...
</p>

</body>
</html>

SeitenanfangSeitenendeEigenschaften

Eigenschaften einer Instanz sind Variablen und müssen Teil der Instanz sein und nicht Teil der Klasse! Letzteres würde dazu führen, dass mehrere Instanzen einer Klasse auf die gleiche Variable zugreifen würden. Im Konstruktor einer Klasse wird ein Hash erzeugt, der weiß, zu welcher Klasse er gehört. Nun ist der Hash nicht nur dazu da, um der Instanz zu sagen, wo es hingehört, sondern man kann in ihm auch Schlüssel-Wert-Paare (dazu ist er eigentlich gedacht) speichern. Damit haben wir den Platz, den wir benötigen, um Eigenschaften abzuspeichern.

Die Eigenschaften AUTHOR und DATE sind neben weiteren Funktionen hinzugefügt worden:

#Klasse smallCGI
package smallCGI;

# ####################
# Konstruktor
sub new {
  my $self=shift;
  my $ref={};

  bless($ref, $self); # nicht &bless schreiben!

  # Eigenschaft DATE setzen:
  $ref->{DATE}=&htmlMetaTime;

  $ref;
}

# ####################
# Ausgabe: HTML-HEAD
sub printHead {
  my $self=shift;
  print "<html>\n<head>\n";

  # gebe Meta-Angaben aus, falls existieren:
  if ($self->{AUTHOR}) {
    print ' <meta name="author" content="';
    print $self->{AUTHOR};
    print "\">\n";
  }
  if ($self->{DATE}) {
    print ' <meta name="date" content="';
    print $self->{DATE};
    print "\">\n";  
  }

  print "</head>\n<body>\n";
}

# ####################
# Ausgabe eines Absatzes
sub printParagraph {
  my $self=shift;
  my $text=shift;
  print "\n<p>\n";
  print $text;
  print "\n</p>\n";
}

# ####################
# Ausgabe: HTML-ENDE
sub printEnd {
  my $self=shift;
  print "\n</body>\n</html>\n";
}

# ####################
# Eigenschaft AUTHOR setzen
sub setAuthor {
  my $self=shift;
  $self->{AUTHOR}=shift;
}

# ####################
# akt. Zeit fuer Metaformat bestimmen
sub htmlMetaTime {
  my @time=localtime(time);
  &format($time[5]+1900,4)."-".&format($time[4]+1,2)."-".&format($time[3],2).
    "T".&format($time[2],2).":".&format($time[1],2).":".&format($time[0],2).'+01:00';
}

# ####################
# formatiert eine Zahl
sub format {
  my $i; my $res="";
  for ($i=$_[1]-length($_[0]); $i>0; $i--) { $res.="0"; }
  $res.$_[0];
}


1;

Erklärung:


use smallCGI;

my $perli=smallCGI->new();
$perli->setAuthor("Hans Mueller, Hintertupfing");

$perli->printHead;
$perli->printParagraph("A simple dynamic HTML-page.\nIt's nice ...");
$perli->printParagraph("Der Autor ist ".$perli->{AUTHOR}.".");

$perli->printEnd;

Und das fällt auf:

<html>
<head>
  <meta name="author" content="Hans Mueller, Hintertupfing">
  <meta name="date" content="2002-06-06T13:41:35+01:00">
</head>
<body>

<p>
Der Autor ist Hans Mueller, Hintertupfing.
</p>

</body>
</html>

SeitenanfangSeitenendePolymorphie

In Perl ist es möglich mehrere Konstruktoren zu schreiben, da ja ein Konstruktor verschiedene Namen haben kann. Diese Konstruktoren können völlig verschieden sein. Die dadurch geschaffene Möglichkeit völlig verschiedene Objekte einer Klasse zu erzeugen, nennt man Polymorphie.


Seitenanfang FehlermeldungHilfe zur Fehlermeldung © 2001-2003 Email an den AutorPerl, Lehrstuhl Mathe II, Uni Bayreuth