[perl] use, include, do und use lib


stso

Mitglied
Hallo,
ich hab folgendes Problem. Ich habe mir in Perl ein paar Klassen geschrieben (was die Objektorientierte Programmierung nennen :(( ). Diese liegen in einem Unterordner des Skriptes von dem ich sie verwenden will. Um diese aufzurufen muss ich in meinem Script
Code:
use classes::ClassA
aufrufen. Jedoch soll in ClassA auch ClassB verwendet werden. Schreibe ich in ClassA jetzt einfach
Code:
use ClassB;   # oder... 
requiere "ClassB.pl";
wird die Datei nicht gefunden. Wahrscheinlich weil im ausführenden Skript das Verzeichnis nicht als "Include"- Verzeichnis geführt wird?! Schreibe ich aber
Code:
do ClassB;
so findet er die Datei erfreulicherweise. Jedoch muss dafür ClassB.pl gesondert im ausführenden Skript ge"use"t oder ge"requiere"t werden. Das will ich nicht, weil ich ja nicht jede Klasse angeben kann die irgendwie mal von der gewünschten Klasse verwendet wird.
Ausserdem hab ich gelesen das, dass do() wohl auch nicht verwendet werden soll da es eine schlechte Performance hat?!

Alternativ kann ich auch in der Klasse welche eine andere Klasse verwendet beim "use" oder "require" den relativen Pfad zum Skript mit angeben. Das sieht dann so aus:
Code:
use classes::ClassB;   # oder...
require "classes::ClassB";
Jedoch würde ich das auch nicht so toll finden da ich dann die Klassen wirklich nur mit dem Skripten verwenden könnte, welche eine Ordner- Hierachieebene über den Klassen sethen. Ich würde die Klassen gern von jeder beliebigen stelle aus benutzen können.

Als nächstes habe ich dann versucht ein zusätliches "include"- Verzeichnis hinzuzufügen.
Code:
use lib "/classes"
Da findet er aber nicht mal ClassA. Verwende ich das "use lib" richtig?

Nun gut, was will ich eigentlich( :) ):
Ich möchte meine Klassen von jedem beliebigen Punkt aus verwenden und will wirklich nur die Klasse "use"n oder "requier"n mit der ich unmittelbar arbeiten möchte. Wenn ich einen kompletten Ordner(mit Unterordnern) "use"n oder "requier"n müsste wäre das nicht so schlimm.

Ich schätze mal die Antwort ist wohl naheliegend aber ich komm nicht drauf.
Ich komme aus der C,C++,C#,Java- Ecke und finde die "Freiheiten" von Perl schon etwas gewöhnungsbedürtig. Bitte verzeicht die dummen Fragen.
 

deepthroat

Erfahrenes Mitglied
Hi.
Als nächstes habe ich dann versucht ein zusätliches "include"- Verzeichnis hinzuzufügen.
Code:
use lib "/classes"
Da findet er aber nicht mal ClassA. Verwende ich das "use lib" richtig?
Grundsätzlich schon - bis auf das fehlende Semikolon.

Aber bist du dir sicher, das der Pfad "/classes" (im Wurzelverzeichnis!) korrekt ist? Meintest du nicht eher "classes"?

Gruß
 

stso

Mitglied
Hi deepthroat,
classes liegt nicht im Wurzelverzeichnis sondern liegt relativ eine Ebene unter meinem "Projekt-" Verzeichnis. Also dem Verzeichnis in dem ich das Skript liegen habe mit dem ich die Klassen verwenden will.

Code:
use lib "/classes";
bezieht sich wohl dann auf das Wurzelverzeichnis(absolut)?! Ich habe es aber relativ gemeint :) .
 

stso

Mitglied
Hallo,
ich habe jetzt noch mal alles ausprobiert. Hier erst mal mein Beispiel. Ich habe die Klassen "ClassA","ClassB" und "ClassC" in einem Ordner Namens "classes" liegen. Die Klassen sehen so aus:

ClassA.pm:
Code:
#

#
package ClassA;
#require "./ClassB.pm";
use ClassB;
#do ClassB;
use strict;

sub new()
{
	my ($class) = @_;
	my $a = {};
	bless($a,$class);
}

sub test()
{
	my ($self) = @_;
	my $b = ClassB->new();
	return "test:".ref($self)."\n\t".$b->test();
}

1;
ClassB.pm:
Code:
#

#
package ClassB;
#require "./ClassC.pm";
use ClassC;
#do ClassC;
use strict;

sub new()
{
	my ($class) = @_;
	my $b = {};
	bless($b,$class);
}

sub test()
{
	my ($self) = @_;
	my $c = ClassC->new();
	return "test:".ref($self)."\n\t".$c->test();
}

1;
ClassC.pm:
Code:
#

#
package ClassC;
use strict;

sub new()
{
	my ($class) = @_;
	my $c = {};
	bless($c,$class);
}

sub test()
{
	my ($self) = @_;
	return "test:".ref($self);
}

1;
Jetzt hab ich einmal ein Skript bei den Klassen liegen. Das sieht so aus:

testABCi.pl
Code:
#

use ClassA;
#use ClassB;
#use ClassC;
use strict;

$a = ClassA->new();
print $a->test();
Das funktioniert solange ich "use" ode "require" in den Klassen verwende. Wenn ich aber "do" in den Klassen verwende muss ich hier noch ClassB und ClassC extra einbinden (hier auskomentiert).
In diesem Zustand funktioniert alles. Jedoch will ich die Klassen auch voon woanders verwenden können. Ich hab daher noch ein Skript auf der selben Ebene wie den Ordner "classes" liegen. Das sieht so aus:

testABCa.pl:
Code:
#

#use lib "/classes"; #(1)
#use lib "classes"; #(2)
#use lib "./classes"; #(3)

#use classes::ClassA; #(4)
#require classes::ClassA; #(5)
#require "classes::ClassA"; #(6)
#require "classes/ClassA.pm"; #(7)

use strict;

$a = ClassA->new();
print $a->test();
Die Zahlen in Klammern (#(X))entsprechen den Versuchen die ich gamacht habe. Zunächst habe ich Versucht den ganzen Ordner und alle enthaltenen "pm"s einzubinden.:
(1): Can't locate object method "new" via package "ClassA" (perhaps you forgot to load "ClassA"?)
(2): Can't locate object method "new" via package "ClassA" (perhaps you forgot to load "ClassA"?)
(3): Can't locate object method "new" via package "ClassA" (perhaps you forgot to load "ClassA"?)

Hier Versuche ich nur ClassA einzubinden da das ja die einzige Klasse ist die ich direkt verwende:
(4): Can't locate ClassB.pm in @INC
(5): Can't locate ClassB.pm in @INC
(6): Can't locate classes::ClassA in @INC
(7): Can't locate ClassB.pm in @INC

Naja, es scheitert meistens daran das er ClassB nicht findet da er nicht in "classes" sucht?! sondern nur an den Orten die in der @INC stehen hat.

LÖSUNG: Ok, jetzt wo ich das Problem nochmal ausformuliert habe bin ich auch auf die Lösung gekommen. Das externe Skript muss so aussehen:

testABCa.pl:
Code:
#

use lib classes
use ClassA;
use strict;

$a = ClassA->new();
print $a->test();
Ok, ich dachte mit 'use lib "classes"' werden automatisch alle Klassen/Module im Ordner "classes" eingebunden. Das ist nicht so! :). ClassA muss wirklich nochmal extra eingebunden werden. Ich hab das mal hier trotzdem gesendet falls mal jemand ein ähnliches Problem hat.

Vielen Dank noch mal an "deepthroat"!
 

Neue Beiträge