Unterklasse von einer Klasse

oraclin25

Erfahrenes Mitglied
Hallo zusammen,

aus der Literatur Java ist auch eine Insel bzgl. anonymer innerer Klassen:

new Klassenname(Optionale Argumente) { ... }.
Steht hinter new ein Klassentyp, dann ist die anonyme Klasse eine Unterklasse von Klassenname. Es lassen sich mögliche Argumente für den Konstruktor der Basisklasse angeben (das ist zum Beispiel dann nötig, wenn die Oberklasse keinen Standardkonstruktor deklariert).

Ich habe einen konkreten Code für diese Klassenart:
Code:
String dateien[] = verzeichnis.list(new TextFilenameFilter());
...

...

class TextFilenameFilter implements FilenameFilter {
		public boolean accept(File pfad, String datei) {
		                     ...
		}
}

TextFilenameFilter ist eine "normale" Klasse, die FilenameFilter implementiert.
Weiter oben ist dann diese anonyme innere Klasse
Code:
 new TextFilenameFilter()

Literatur lehrt: "Steht hinter new ein Klassentyp, dann ist die anonyme Klasse eine Unterklasse von Klassenname"
Dies trifft zu, hinter new ist ein Klassentyp und kein Interface. Demnach müsste ja die anonyme Klasse eine Unterklasse von Klassenname.
Der Klassenname ist hierbei --> TextFilenameFilter.

Was ist dann hier die Unterklasse von diesem Klassennamen :rolleyes:? Habe ich hier einen Denkfehler?

Danke zusammen.

Schöne Grüße aus Rheinland,

Eure Ratna:p
 
Hi

Denkfehler: Du hast hier nämlich überhaupt keine anonyme Klasse.

(Annahme für die weiteren Erklärungen: verzeichnis.list will einen FilenameFilter als Parameter)

Deine Variante:
TextFilenameFilter ist eine ganz echte Klasse,
die FilenameFilter implementiert und eine Methode accept hat.

In der Codezeile oben legst du ein Objekt von TextFilenameFilter an
und übergibst es auch gleich an list
(da TextFilenameFilter ja auch ein FilenameFilter ist bzw.
alle Methoden anbietet, die FilenameFilter auch hat, geht das)


Mit einer anonymen Klasse wäre es so:
Java:
String dateien[] = verzeichnis.list(
    new FilenameFilter () {
        public boolean accept(File pfad, String datei) {
                             ...
        }
  }
);
Es gibt überhaupt kein TextFilenameFilter.
Und zum Übergeben machst du eine Instanz von etwas,
dass FilenameFilter erbt/implementiert und die Methode accept hat.
Und dieses Etwas ist die anonyme Klasse.
Die ganze Klasse, nur ohne Namen, steht da als Parameter drin,
wird adhoc so erstellt, du hast das Objekt davon, und das wars dann wieder.

Intern wirds dann vom Compiler wieder in etwas Ähnliches wie das aufgetrennt:
Java:
String dateien[] = verzeichnis.list(new Class0001());

class Class0001 implements FilenameFilter {
        public boolean accept(File pfad, String datei) {
                             ...
        }
}
Nur wirklich geben tuts dieses Class0001 nicht,
und man kann nicht irgendwo anders noch ein new Class0001() machen.
 
Hallo sheel,

vielen Dank.

Code:
String dateien[] = verzeichnis.list(new Class0001());
 
class Class0001 implements FilenameFilter {
        public boolean accept(File pfad, String datei) {
                             ...
        }
}

Okay, ich habe also ein Objekt, dieses wird direkt an die Methode list übergeben. Mich wunderts, beim obigen Code, woher weiss der Compiler, dass der Pfad aus verzeichnis an die Variable "pfad" referenziert wird? Und dass die einzelnen Dateien in verzeichis einzeln an die Variable "datei" übergeben wird?

Also, mich machts stutzig, dass hierbei
Code:
String dateien[] = verzeichnis.list(new Class0001());
keinerlei Parameter-Übergabe an Class0001 stattfindet.

Ich meine, es ist ja schön, dass man wie oben so direkt verwenden kann, aber woher soll man wissen, dass keine Parameterübergabe stattfindet?

Ich hoffe, meine Frage ist verständlich?

Vielen lieben Dank.

Schöne Grüße aus Rheinland,

Eure Ratna
 
Java:
Klasse x = new Klasse("meinpfad");
x.accept();

Java:
Klasse x = new Klasse();
x.accept("meinpfad");
Merkst den Unterschied?

Beim new, also beim Konstruktor, braucht die Klasse keine Parameter.
Aber wenn man accept aufrufen will muss man dem Parameter mitgeben.

list hat das Objekt übergeben bekommen und kann von dem accept aufrufen,
so oft und womit es will.
 
Danke sheel,

och je.. ich weiss nicht, warum ich das noch nicht kapiere.

Code:
String dateien[] = verzeichnis.list(new TextFilenameFilter());
...
 
...
 
class TextFilenameFilter implements FilenameFilter {
        public boolean accept(File pfad, String datei) {
                             ...
        }
}

Also, ich habe verstanden dass hier ein Objekt der echten Klasse TextFilenameFilter erzeugt und an list übergeben wird. Aber ich sehe das so, dass was darauf folgt, ja eigentlich nur das Überschreiben von Methode accept. Es ist sogar kein Aufruf von accept. Also, einige Punkte, die mich stutzig machen:
1. Es findet eigentlich kein Methodenaufruf statt
2. Der Compiler weiss komischerweise, dass pfad das Objekt verzeichnis übergeben bekommen. Analog, er weiss dass datei die einzelnen Dateien im Verzeichnis übergeben bekommt

Das Beispiel von Dir:
Code:
Klasse x = new Klasse("meinpfad");
x.accept();
Hier findet ja explizit ein Methodenaufruf statt, oder? Hingegen da oben, könnte man nicht erkennen, dass accept aufgerufen wird.

Ich weiss nicht, ob ich das jemals verstehen werde.

Schöne Grüße aus Rheinland,

Eure Ratna
 
Beim unteren Code findet explizit ein Aufruf von accept statt, genau.
Beim oberen Code nicht, richtig.
Was im oberen Code aufgerufen wird ist list (als Teil von verzeichnis).

Du hast den Code von list zwar nicht, aber es ist auch eine normale Methode.
Sinn ist, sich alle Dateinamen in ein Array zu holen und mit return zurückzugeben.
Aber: Nur die Dateinamen ins Array sammeln,
die eine (vom Programmierer festgelegte) Überprüfung bestehen.

Und jetzt muss list natürlich wissen, welche Dateiname
für dich gut sind (ins Array kommen) und welche nicht.
Dafür hätte es gern irgendwas, dass ein "accept" zum aufrufen hat.
In list wird accept aufgerufen, für jede gefundene Datei.
(Nur hast du den Code von list eben nicht).
Und der Ja/Nein-Rückgabewert von accept entscheidet dann,
ob die Datei mit ins Array aufgenommen wird.

Um sicherzustellen, dass das übergebene Objekt von Wasauchimmer
ein passendes accept hat gibts eben ein Interface mit diesem accept,
und list nimmt alles, was dieses Interface FilenameFilter implementiert.
(Wenn kein accept drin wäre würde sich dann schon der Compiler beschweren,
dass die Klasse nicht zum Interface passt).

Rein codemäßig kann ich hier auch nicht erkennen, ob list in sich accept aufruft.
Das liegt nicht am fehlenden Verständnis.
Aber a) List will unbedingt etwas mit FilenameFilter.
Die einzige Methode, die FilenameFilter vorschreibt, ist dieses accept.
Warum solls also sonst ein FilenameFilter brauchen, wenns accept nicht verwendet?
und b) Wenn man sich den Zweck von list durchdenkt
bzw. in die Doku schaut machts einfach Sinn (was zwar keine Garantie ist, aber...)


Nochmal nur anonymen Klasse:
Du brauchst jetzt also irgendwas, was accept hat und FilenameFilter implementiert.

Wenns im Programm schon sowas gibt: Übergib das einfach.

Wenns noch nichts gibt, du das aber öfter brauchst:
Bring die Methode accept irgendwo passend in eine bestehende Klasse unter
oder mach ggf. eine Neue.

Wenns nichts gibt und du das Ganze nur an der einen Stelle brauchst:
Dann eben die anonyme Klasse.
Direkt rein und keine weiteren Gedanken daran verschwenden.
(ob das "schön" ist ist eine andere Sache).
 
Hallo sheel,

In list wird accept aufgerufen, für jede gefundene Datei.
(Nur hast du den Code von list eben nicht).

na, logisch.. Der Satz oben war für mich der Knackpunkt, ich bin jetzt glücklich. Ich glaube, ich bin doch nicht so dumm, vielleicht etwas langsam :rolleyes:

Vielen lieben Dank sheel, bis bald..

Schöne Grüße aus Rheinland,

Eure Ratna
 
Hallo zusammen,

@sheel, mhh.. ich habe nun verstanden, warum quasi "kein sichtlicher Methodenaufruf" stattfindet. Der accept-Aufruf findet in der Tat intern in File.list statt. Uns Programmierern verlangt File.list lediglich die Filter-Struktur, alles andere erledigt die Methode File.list. Hört sich gut an oder? :rolleyes:

Ich habe ja folgenden Code vorliegen:
Code:
String ergebnisdateien[] = verzeichnis.list(new TextFilenameFilter());
...
...

...

class TextFilenameFilter implements FilenameFilter {
		public boolean accept(File pfad, String datei) {
		      //meine Filterimplementierungen
                                       //meine Filterimplementierungen
                                       //meine Filterimplementierungen
		}
}

Soweit so gut. Da bin ich gestern Nacht kurz vorm Eingeschlafen auf die Frage gekommen: Wie wärs, wenn die Klasse TextFilenameFilter noch weitere "eigenen" Methoden implementiert? Also, so ungefähr:

Code:
class TextFilenameFilter implements FilenameFilter {
		public boolean accept(File pfad, String datei) {
		      //meine Filterimplementierungen
                                       //meine Filterimplementierungen
                                       //meine Filterimplementierungen
		}

                                 public int ratnasMethode(Object a){
                                       a = new Tier();
                                 }

File.list zieht ratnasMethode sicherlich nicht in Betracht, oder? Gut, in dem Fall ist es sicherlich logisch, da die Schnittstelle FilenameFilter ja lediglich eine Methode hat(nämlich dieses accept). Bei der Schnittstelle Comparator siehts ein bisschen anders aus, Comparator hat 2 Methoden(compare und equals). So, darf frau dann nur diejenige Methode überschreiben bzw. definieren, die frau braucht?

Schönen Dank.

Schöne Grüße aus Rheinland,

Eure Ratna:p
 
Du kannst so viel zusätzliche Methoden/Variablen reinmachen, wie du willst.
Die Verwender wie list stören sich nicht daran.
Brauchen nur "mindestens" ihre vom Interface geforderten Methoden,
der Rest ist egal.

Man kann die anderen Methoden auch von accept aus verwenden,
wenns hilft, das Ergebnis zu ermitteln
(bzw. accept aufgrund der Länge in mehrere Methoden aufteilen
und in accept selber die Hilfsmethoden aufrufen).
 
Hallo sheel,

"Die Verwender wie list brauchen nur "mindestens" ihre vom Interface geforderten Methoden"

Angenommen, ein Interface hat 3 Methoden(Method_a, Method_b und Method_c), die in der echten Klasse dann unbedingt zu implementieren sind. So, wird gemacht.. So, ich als Programmiererin möchte aber lediglich Mehod_a verwenden. Wie wärs dann? Wie bringe ich dem Compiler bei, dass lediglich die Method_a in Betracht gezogen werden soll.

Vielen Dank.

Schöne Grüße aus Rheinland,

Eure Ratna
 
Zurück