Konstruiert Java dot neu einen Code-Geruch? [geschlossen]

8

Vor kurzem hatte ich Gelegenheit, Javas & lt; Instanz & gt; .new zu verwenden Konstruieren, um eine Instanz einer inneren Klasse zu erstellen.

Obwohl ich der Meinung bin, dass es eine vernünftige Begründung dafür gibt, scheint seine eher obskure Syntax es für Wartungsprogrammierer etwas schwieriger zu machen.

Aber ich frage mich, ob die Notwendigkeit für & lt; instance & gt; .new ein Indikator dafür ist, dass es besser wäre, ein bisschen Refactoring zu machen, um die innere Klasse zu einer Klasse der obersten Ebene in ihrem Elternpaket zu machen, geben Sie ihr einen Konstruktor Ein Verweis auf seinen übergeordneten Typ wäre ideal und fügt den Feldern, auf die er vom übergeordneten Typ zugreift, Zugriffsmethoden oder Zugriffsmodifizierer auf Paketebene hinzu.

Gibt es Anwendungsfälle für & lt; instance & gt; .new, die nicht durch Umgestaltung der inneren Klasse in eine äußere Klasse behandelt werden konnten?

    
Kylos 27.09.2012, 15:05
quelle

5 Antworten

2

Ich hätte nicht gesagt, dass es Code-Geruch ist.

Wenn die Kopplung zwischen der äußeren und der inneren Klasse stark ist und Ihre Verwendung der inneren Klasse für eine gute Verkapselung steht, dann würde ich sagen, dass Sie dieses Konstrukt verwenden. Auf der anderen Seite, wenn die Abstraktion bereits undicht ist, ist es wahrscheinlich eine bessere Idee, die innere Klasse zu einer Klasse auf oberster Ebene zu machen.

Die Verwendung von outer.new Inner() kann oder kann nicht der Beweis für eine undichte Abstraktion sein.

(Das Konstrukt wurde aus gutem Grund in die Sprache aufgenommen, und die Tatsache, dass es nur selten benötigt wird, macht seine Verwendung nicht ungültig.)

    
Stephen C 27.09.2012, 15:10
quelle
4
  

Gibt es Anwendungsfälle für .new, die nicht durch Umgestaltung der inneren Klasse in eine äußere Klasse behandelt werden könnten?

Es gibt im Allgemeinen keine wichtigen Anwendungsfälle für diese Syntax, da Sie den inneren Konstruktor immer verbergen können und die äußere Klasse innere Klasseninstanzen durch Factory-Methoden zurückgeben kann (wenn Sie den inneren Typ trotzdem nach außen offen legen wollen):

%Vor%

Kundencode:

%Vor%

Also ist der "Code-Geruch" (wenn es wirklich ein Code-Geruch ist) nicht in der Tatsache, dass eine innere Klasse vorhanden ist, sondern in der Tatsache, dass sein Konstruktor öffentlich verfügbar ist (und verwendet wird). Aber nach einer sorgfältigen Auswertung könnten Sie feststellen, dass dies in Ordnung ist

UPDATE : Ein gutes Zeichen dafür, dass die Kapselung unterbrochen ist, ist, wenn Outer Instanzen wahrscheinlich eine kürzere Lebensdauer haben als Inner Instanzen. In diesem Fall können Inner -Instanzen einen Verweis auf Outer für einen längeren Zeitraum behalten, als der Autor des Outer beabsichtigt hat. Dies kann sogar zu Speicherlecks führen.

    
Lukas Eder 27.09.2012 15:10
quelle
0

Nun, von einer inneren Klasse haben Sie Zugriff auf private Mitglieder der äußeren Klasse. Top-Level-Klassen nicht.

Aber Sie könnten der äußeren Klasse eine Factory-Methode hinzufügen, die eine neue Instanz der inneren Klasse erstellt.

    
Puce 27.09.2012 15:11
quelle
0

Wenn Sie innere Klassen verwenden, wird Ihr Code schwieriger zu verstehen, da die Klassen ihren inneren Zustand teilen und daher mit dem Prinzip der Informationsverbergung brechen. Manchmal kann die Verwendung einer inneren Klasse eine Lösung leicht zu schreiben machen, aber ich denke, dass es die meiste Zeit nicht die beste / sauberste Lösung ist.

    
CQQL 27.09.2012 15:17
quelle
0

Ich benutze innere Klasse vor allem, wenn eine Methode einer Klasse Multithread sein muss.

Tatsächlich gibt es zwei saubere Möglichkeiten, Threads zu deklarieren:

  • Erstellen Sie eine Runnable -Klasse (die Methode enthält Multithread) und lassen Sie den Client selbst einen neuen Thread erstellen. Der Nachteil ist, dass der Client sich bewusst sein muss, dass er mit Multithreading umgehen muss.

  • Geben Sie die Jobklasse nicht als Runnable an, sondern definieren Sie lieber eine inner-class , die selbst Runnable implementiert. Natürlich muss diese inner-class nicht public sein und wird daher von einer der öffentlichen dedizierten Methode in der äußeren Klasse (dh der Job-Klasse) instanziiert. Daher behandelt der Client diese public -Methode, ohne zu wissen, dass ein Thread im Hintergrund erstellt wird. Wenn Entwickler sich morgen dafür entscheiden, das Multithreading innerhalb dieser Jobklasse aus irgendeinem Grund zu entfernen, kann der Client vollständig unverändert bleiben.

Und damit diese innere Klasse Felder der äußeren Klasse erbt, deklariere ich sie nicht als statisch. (auch verschachtelte Klasse im Gegensatz zur inneren Klasse genannt)

    
Mik378 27.09.2012 15:23
quelle