Hallo !
[...]
Wenn's dir wirklich um handfeste Objektorientiertheit gehen würde, dann würdest du sicherlich etwas anderes als Perl benutzen. Dessen Objektorientiertheit läßt ja, genau wie PHP 4, viele Dinge vermissen.
Interfaces
Perl-Klassen haben Interfaces.
Oder meinst Du damit "Interfaces wie in Java" ? Oder C++ Klassen, die ( ggf. ausschliesslich ) rein virtuelle Methoden beinhalten (virtual f() = 0;) ?
Wie man's nimmt. Es ist schon moeglich, Funktionen ohne Implementierung in fuer Perl-Klasse zu deklarieren. Das bewahrt mich allerdings nicht davor, diese abstrakte Funktion dann auch aufzurufen.
Das ist uebrigens auch mit DER imo objektorientierten Sprache schlechthin, naemlich C++, moeglich - man muss sich nur "Muehe" geben:
/*
* pure-virtual.cpp
* Calls an abtract method at a VERY incovenient moment..
*/
/* abstract */ class A {
protected:
virtual void foo() = 0;
void bar() { foo(); };
public:
A() {
// ...namely here, where the VMT is not yet readied !
bar();
}
};
class B : public A {
protected:
virtual void foo(){};
public:
B() : A(){};
};
int main ( int argc, char* argv[]) {
B b; // ..and get outta here !
return 0;
}
// EOF pure-virtual.cpp
g++-3.3 pure-virtual.cpp
./a.out
pure virtual method called
Aborted
Das "klappt" mit dem g++; mit den MS Compilern( >5.0 ?) wenn "Construction displacement" abgeschaltet hat. Was ich immer tue um sowas von vornherein zu unterdruecken.
Der Code vestoesst natuerlich sowieso gegen die Faustregel, in Konstruktoren moeglichst nur nicht-virtuellen Code einzusetzen.
und private bzw. geschützte Eigenschaften und Methoden beispielsweise.
my
Nicht das ganze Objekt. Aber die Dinge, die die Methode braucht, und die ggf. fehlschlagen können. Wie eine fehlende DB-Verbindung oder eine ungeöffnete Datei, weil der Konstruktor nicht aufgerufen wurde.
Das waere ja nicht so schlimm; ob die DB oder eine Datei noch 'da' ist wenn ich auf darauf zugreife, muss ich ja sowieso pruefen.
Schlimmer waere doch wenn ich jede Instanz-Variable auf Gueltigkeit und ggf. auf Vorhandensein pruefen muesste.
Gerne kann man daraus natürlich auch eine Grundvereinbarung machen: Der Konstruktor setzt im Objekt immer ein Flag - und wenn die Methode das Flag nicht findet, ist sie wohl statisch aufgerufen worden.
Von Flags halte ich gar nichts; wenn das irgendwie anders geht wuerde ich immer eine andere Loesung waehlen.
Durch Flags und "last if" und "if (...) return" wird Code unuebersichtlich.
Würde ich einer Log-Klasse noch eine prozedurale Schnittstelle geben wollen, würden die Prozeduren ganz schlicht die Methoden der Klasse aufrufen, und fertig.
Wie soll ich die Methofden dann nennen um sie von den Klassenmethoden zu unterscheiden ?
_log() ; real_log() ? ; eigentliches_log() ? ;-)
Da waere mir die skizzierte Praeambel-Loesung doch noch lieber.
Es ist nun mal so, dass man mit Code ziemlich viel erreichen kann - aber je mehr man erreichen muß, desto komplizierter wird's.
Und eine Log-Klasse ist nun beileibe kein einfaches Ding.
Hab mich fuer ein "fettes" Modell entschieden, das von einem Moderator - naemlich einer (Singleton-)Application-Klasse komponiert wird.
Dort werden durch addSink() sinks ( STDOUT/STDERR, SYSLOG, FILE, DB) samt Formatierern ( PLAIN, XML ) eingebunden und die Verbosity ( NOTE, TRACE ) soll von aggregierten Strategie-Objekten gesteuert werden
Mi dem Log zieh ich sozusagen eine ganze Familie von Klassen gross, die spaeter ueberall eingestzt werden koennen.
Mal gucken wie das so mit Perl laeuft.
Gruss
Holger