NAME

ClassLoader - Load class modules automatically

SYNOPSIS

use ClassLoader;

my $obj = MyClass->new; # loads MyClass.pm

DESCRIPTION

(This module is documented in German)

Zweck

Muede, use-Anweisungen fuer das Laden von Perl-Klassen zu schreiben?

Dieses Modul reduziert den Aufwand fuer das Laden von Klassen auf die Anweisung:

use ClassLoader;

Danach werden alle Klassen automatisch mit ihrem ersten Methodenaufruf geladen. Dies geschieht bei jeder Methode, gleichgueltig, ob Klassen- oder Objektmethode.

Vorteile

  • Man muss keine use-Aufrufe mehr schreiben.

  • Es werden nur die Klassen geladen, die das Programm tatsaechlich benoetigt.

  • Die Startzeit des Programms verkuerzt sich.

  • Das Programm benoetigt unter Umstaenden weniger Speicher, da keine ueberfluessigen Module geladen werden.

Was ist ein Klassen-Modul?

Unter einem Klassen-Modul verstehen wir eine pm-Datei, die eine Klasse definiert, d.h. die

  1. ein Package mit dem Namen der Klasse deklariert,

  2. unter dem Namen des Package gemaess den Perl-Konventionen im Dateisystem abgelegt ist,

  3. ihre Basisklassen (sofern vorhanden) selbstaendig laedt.

Beispiel

Eine Klasse A::B::C sei in einer Datei mit dem Pfad A/B/C.pm definiert (welche via @INC gefunden wird), welche den Inhalt hat:

package A::B::C;
use base qw/<BASECLASSES>/;

<METHODS>

1;

Das Laden der Basisklassen-Module geschieht hier mittels use base. Es ist genauso moeglich, die Basisklassen-Module per use zu laden und @ISA zuzuweisen, was aber umstaendlicher ist.

Eine pm-Datei, die diesen Konventionen genuegt, ist ein Klassen-Modul und wird von ClassLoader automatisch beim ersten Methodenzugriff geladen.

Wie funktioniert das?

ClassLoader installiert sich als Basisklasse von UNIVERSAL und definiert eine Methode AUTOLOAD, bei welcher saemtliche Methodenaufrufe ankommen, die vom Perl-Interpreter nicht aufgeloest werden koennen. Die AUTOLOAD-Methode laedt das benoetigte Klassen-Modul (sofern vorhanden) und ruft die betreffende Methode auf (sofern vorhanden). Existiert das Klassen-Modul nicht oder enthaelt es die gerufene Methode nicht, wird eine Exception ausgeloest.

Die AUTOLOAD-Methode, die ClassLoader definiert, ist recht einfach (Fehlerbehandlung hier vereinfacht):

sub AUTOLOAD {
    my $this = shift;
    # @_: Methodenargumente

    my ($class,$sub) = our $AUTOLOAD =~ /^(.*)::(\w+)$/;
    return if $sub !~ /[^A-Z]/;

    eval "use $class";
    if ($@) {
        die "Modul kann nicht geladen werden\n";
    }

    unless ($this->can($sub)) {
        die "Methode existiert nicht\n";
    }

    return $this->$sub(@_);
}

Lediglich der erste Methodenaufruf einer (noch nicht geladenen) Klasse laeuft ueber diese AUTOLOAD-Methode. Alle folgenden Methodenaufrufe der Klasse finden direkt statt, also ohne Overhead! Methodenaufrufe einer explizit geladenen Klasse laufen von vornherein nicht ueber die AUTOLOAD-Methode.

Was passiert im Fehlerfall?

Schlaegt das Laden des Moduls fehl oder existiert die Methode nicht, wird eine Exception ausgeloest.

Damit der Ort des Fehlers einfach lokalisiert werden kann, enthaelt der Exception-Text ausfuehrliche Informationen ueber den Kontext des Fehlers, einschliesslich Stacktrace.

Aufbau des Exception-Texts:

Exception:
    CLASSLOADER-<N>: <TEXT>
Class:
    <CLASS>
Method:
    <METHOD>()
Error:
    <ERROR>
Stack:
    <STACKTRACE>

Mittels Test auf das Exception-Kennzeichen "CLASSLOADER-ltN>" kann unabhaengig vom Fehlertext auf einen bestimmten Fehler geprueft werden:

$obj = eval { MyClass->new };
if ($@ =~ /CLASSLOADER-00001/) {
    # Modul MyClass.pm konnte nicht geladen werden
    ...
}

Gibt es Probleme, wenn eine Klasse selbst eine AUTOLOAD-Methode hat?

Nein, denn die AUTOLOAD-Methode von ClassLoader wird vor dem Laden der Klasse angesprochen. Alle spaeteren Methoden-Aufrufe der Klasse werden ueber die Klasse selbst aufgeloest. Wenn die Klasse eine AUTOLOAD-Methode besitzt, funktioniert diese genau so wie ohne ClassLoader.

METHODS

Autoload

Die folgende AUTOLOAD-Methode implementiert die Funktionalitaet des Moduls. Sie ist privat, wird nicht direkt, sondern vom Perl-Interpreter gerufen, wenn eine Methode nicht gefunden wird.

AUTOLOAD() - Lade Klassen-Modul

$this->AUTOLOAD;

Lade Klassen-Modul und fuehre den Methodenaufruf durch. Die Argumente und der Returnwert entsprechen denen der gerufenen Methode. Schlaegt das Laden des Moduls fehl, loest die Methode eine Exception aus (siehe oben).

CAVEATS

  • Der Mechanismus funktioniert nicht, wenn der Modulpfad anders lautet als die Klasse heisst. Solche Module muessen explizit per use geladen werden.

  • Sind mehrere Klassen in einer Moduldatei definiert, kann das automatische Laden logischerweise nur ueber eine dieser Klassen erfolgen. Am besten laedt man solche Module auch explizit.

  • Ueber Aufruf der Methode import() ist es nicht moeglich, ein Modul automatisch zu laden, da Perl bei Nichtexistenz von import() AUTOLOAD() nicht aufruft, sondern den Aufruf ignoriert. Man kann durch $class->import() also nicht das Laden eines Klassen-Moduls ausloesen.

  • Module, die nicht objektorientiert, sondern Funktionssammlungen sind, werden von ClassLoader nicht behandelt. Diese muessen per use geladen werden.

EXCEPTIONS

CLASSLOADER-00001: Modul kann nicht geladen werden
CLASSLOADER-00002: Methode existiert nicht

AUTHOR

Frank Seitz, http://www.fseitz.de/

COPYRIGHT

Copyright (C) Frank Seitz 2008-2010

LICENSE

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.