Blog

Ein großer Klassenunterschied: class

01.08.2023 // Renée Bäcker

Die (native) Objektorientierung in Perl hat viele Vorteile gegenüber anderen Programmiersprachen, aber auch viele Nachteile. Das ist mit ein Grund, warum Module wie Moose oder Moo so beliebt wurden. Schon seit längerer Zeit gab es Überlegungen, ein neues Objektmodell im Perl-Core umzusetzen – Stichwort: Cor(inna).

Mit Perl 5.38 ist es soweit, dass dieses neue Objektmodell umgesetzt wurde (vorerst im experimentellen Status)... Mit dem neuen Feature class gibt es die neuen Schlüsselwörter class, field und method. Hier eine kleine Beispielklasse:

use v5.38;

use experimental 'class';

class Schulung 0.01 {
    field $date :param;
    field $name :param(title);
    field @persons;

    method info {
        say sprintf 'Die Schulung "%s" findet am %s statt', $name, $date;
    }   
    
    method register ( $person ){
        push @persons, $person;

        say "Vielen Dank für die Anmeldung!";
        $self->info;
    }   
    
    method attendee_list {
        say sprintf "Teilnehmer (%s):\n%s", $name, "-" x 45;
        say join "\n", @persons;
    }   
} 

Die ersten 3 Zeilen sind dafür da, dass wir die Features von Perl 5.38 und das neue Objektmodell nutzen können. Ab der 5. Zeile definieren wir die Klasse Schulung in der Version 0.01.

Mit field legen wir fest, welche Attribute die Objekte haben. Diese fields sind außerhalb der Klasse nicht sichtbar. Über das :param-Attribut wird festgelegt, welche Parameter dem Konstruktor (die Methode new gibt es automatisch) übergeben werden können bzw. müssen. Für diese Klasse wird ein neues Objekt so erzeugt:

my $schulung = Schulung->new(
    date  => '23.09.2023',
    title => 'Neue Features in Perl 5.38',
);

Für das Objektattribut date müssen wir auch einen Wert zum Schlüssel date übergeben. Für das Attribt name wurde über :param(title) festgelegt, dass bei der Objekterzeugung der Schlüssel title genutzt werden muss.

Lässt man z.B. date weg, bekommt man eine passende Fehlermeldung:

Required parameter 'date' is missing for "Schulung" constructor at schulung.pl line 8.

Für optionale Objektattribute muss man einen Standardwert angeben, z.B.

field $date :param = localtime;

Für Methoden gibt es in dem neuen Objektmodell das Schlüsselwort method. Subroutinen können auch in den neuen Klassen verwendet werden. Der große Unterschied ist, dass in methoden die Variable $self (in der das Objekt steckt) automatisch vorhanden ist und dass methoden mit einem Objekt aufgerufen werden müssen. Wird das nicht gemacht, bekommt man die Fehlermeldung

Cannot invoke method "attendee_list" on a non-instance at Schulung.pm line 31.

Die Methodensignaturen funktionieren genauso wie die Subroutinensignaturen, die es schon länger im Perl-Core gibt und seit Perl 5.36 nicht mehr experimentell sind.

Ansonsten gibt es noch die Möglichkeit, einen ADJUST-Block zu nutzen, um die Parameter des Konstruktors anzupassen:

ADJUST {
    $date = Time::Piece->strptime( $date, '%d.%m.%Y' ) 
        if !( $date isa 'Time::Piece' );
}

Im ADJUST-Block gibt es auch automatisch die Instanzvariable $self. Wenn mehrere ADJUST-Blöcke definiert werden, werden diese in der Reihenfolge der Definition ausgeführt.

Das neue Objektmodell erlaubt nur Einfachvererbung, wobei die Klasse von der geerbt wird auch eine Klasse nach dem neuen Objektmodell sein muss und keine herkömmliche Klasse sein darf. Für die Vererbung wird das Klassenattribut :isa verwendet:

class Schulung :isa( Event ) {
    ...
}



Permalink: