Thread AUTOLOAD ist übler Hack (13 answers)
Opened by Muffi at 2015-01-13 10:43

rosti
 2015-01-14 10:24
#179223 #179223
User since
2011-03-19
3196 Artikel
BenutzerIn
[Homepage]
user image
Hi lieber Kollege,

dann lass uns das mal zusammen durchnehmen. Vorab: UNIVERSAL::can wird NICHT verbogen, alles bleibt wie's ist. Mal angenommen, die sub AUTOLOAD{} definieren wir in der main und rufen einfach eine Funktion auf:

Code (perl): (dl )
main->configini($path_ini_file); # 'main' als Ersatz für eine Instanz


Der Interpreter sucht die sub AUTOLOAD{}, weil configini() nirgendwo zu finden ist. Innerhalb der sub AUTOLOAD{} befragen wir eine Variable our $AUTOLOAD, im Beispiel steht da drin: main::configini. Und interessiert nur der das Word ganz hinten und das findet die RE (\w+)$.

Vereinbarungsgemäß liegen die Dateien in @INC/auto als 'name.pm', fürs Beispiel muss es da eine configini.pm geben und die wird mit require eingebunden. Nun die Datei, da steht drin:

Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# File auto/configini.pm
# keine package-Deklaration, es greift der default: package main;

use strict;
use warnings;
use Config::Tiny;

my $CFT = Config::Tiny->new; # gilt nur dateiweit

# hier die Definition der Funktion
sub configini{
    my $self = shift;
    my $file = shift;
    return $CFT = Config::Tiny->read($file) || do{
        $@ = "Error with CFG-File '$file': $Config::Tiny::errstr";
        undef;
    };
        
}
1;


Nun, require kompiliert die Datei und configini() liegt dann in der Symboltabelle. D.h., bei weiteren Aufrufen configini() greift die sub AUTOLOAD{} gar nicht mehr, sie greift also nur einmal. Da configini() in der Symboltabelle liegt, liefert UNIVERSAL::can() eine Referenz auf den CODE, der sodann über die Instanz aufgerufen werden kann mit allen Argumenten in @_.

Vererbung: Eine sub AUTOLOAD{} wird vererbt wie jede andere Funktion. Wenn die Subklasse von der main erbt, können Autoload-Methoden sowohl mit als auch ohne echte Klasseninstanz aufgerufen werden. In der Autoload-Methoden-Dateien kann der Name der package != main deklariert sein. Mit der von mir in den Beispielen vorgeschlagenen Fehlerbehandlung ergibt sich ein aufgeräumter Code ;)

View full thread AUTOLOAD ist übler Hack