Betrachten Sie den folgenden Konstruktor für die Klasse Foo
(was der Übersichtlichkeit halber nicht einer generischen Klasse ist):
Dies ist eine gültige Syntax für Konstruktoren, genau wie bei normalen generischen Methoden .
Aber was nützt diese Syntax? In der Regel bieten generische Methoden Typsicherheit für ihren Rückgabetyp und können vom Typrückschluss durch den Compiler profitieren. Zum Beispiel:
%Vor%Aber ein Aufruf an einen Konstruktor gibt immer eine Instanz seiner deklarierenden Klasse zurück, so dass seine Typparameter keine Auswirkung auf den Rückgabetyp haben. Der obige Konstruktor könnte einfach durch seine Löschung ersetzt werden:
%Vor%Natürlich geht es bei Generika nicht nur um die Typsicherheit für Rückgabetypen. Der Konstruktor möchte vielleicht nur die Art der übergebenen Argumente beschränken. Die obige Argumentation gilt jedoch immer noch für einen beschränkten Typparameter:
%Vor%Sogar verschachtelte Typparameter mit Begrenzungen werden mit Platzhaltern behandelt:
%Vor%Was ist also ein zulässiger Anwendungsfall für einen generischen Konstruktor?
Hier ist ein mögliches, angepasst von der funktionalen Programmierung. Angenommen, wir haben einen Stream
-Typ, der einen internen Status hat und wiederholt neue Elemente liefert, bis null
zurückgegeben wird. Den externen Anrufern ist es egal, wie der interne Statustyp des Streamtyps aussieht. Sie könnten also etwas wie
ohne dass der Empfänger wissen muss, wie der interne Zustandstyp ist.
Betrachten Sie den folgenden Konstruktor für die Klasse %code% (was der Übersichtlichkeit halber nicht einer generischen Klasse ist):
%Vor%Dies ist eine gültige Syntax für Konstruktoren, genau wie bei normalen generischen Methoden .
Aber was nützt diese Syntax? In der Regel bieten generische Methoden Typsicherheit für ihren Rückgabetyp und können vom Typrückschluss durch den Compiler profitieren. Zum Beispiel:
%Vor%Aber ein Aufruf an einen Konstruktor gibt immer eine Instanz seiner deklarierenden Klasse zurück, so dass seine Typparameter keine Auswirkung auf den Rückgabetyp haben. Der obige Konstruktor könnte einfach durch seine Löschung ersetzt werden:
%Vor%Natürlich geht es bei Generika nicht nur um die Typsicherheit für Rückgabetypen. Der Konstruktor möchte vielleicht nur die Art der übergebenen Argumente beschränken. Die obige Argumentation gilt jedoch immer noch für einen beschränkten Typparameter:
%Vor%Sogar verschachtelte Typparameter mit Begrenzungen werden mit Platzhaltern behandelt:
%Vor%Was ist also ein zulässiger Anwendungsfall für einen generischen Konstruktor?
Ein Anwendungsfall, den ich mir vorstellen kann, ist, wenn Sie ein Konstruktorargument auf mehr als einen Typ beschränken wollen. Nur die generische Syntax erlaubt es Ihnen, einen Konstruktor zu deklarieren, der ein %code% von %code% s übernimmt, das auch %code% implementiert:
%Vor%Sie können bestimmte Einschränkungen für die Konstruktorparameter erzwingen. Z.B. Der folgende Code erfordert zwei Parameter, die die Schnittstellen InterfaceA und InterfaceB implementieren.
%Vor%Die Hauptanwendung besteht darin, sicherzustellen, dass Typeinschränkungen zwischen mehreren Parametern eingehalten werden. Hier ist ein Beispiel, das eine Reihe von Komponenten in der richtigen Reihenfolge auf einer Fertigungslinie platziert:
%Vor%Hier stellt %code% sicher, dass %code% und %code% denselben Typ %code% und nicht (sagen wir), %code% und %code% enthalten.
Hier ist ein mögliches, angepasst von der funktionalen Programmierung. Angenommen, wir haben einen %code% -Typ, der einen internen Status hat und wiederholt neue Elemente liefert, bis %code% zurückgegeben wird. Den externen Anrufern ist es egal, wie der interne Statustyp des Streamtyps aussieht. Sie könnten also etwas wie
erhalten %Vor%ohne dass der Empfänger wissen muss, wie der interne Zustandstyp ist.
Ein Anwendungsfall, den ich mir vorstellen kann, ist, wenn Sie ein Konstruktorargument auf mehr als einen Typ beschränken wollen. Nur die generische Syntax erlaubt es Ihnen, einen Konstruktor zu deklarieren, der ein List
von Number
s übernimmt, das auch RandomAccess
implementiert:
Die Hauptanwendung besteht darin, sicherzustellen, dass Typeinschränkungen zwischen mehreren Parametern eingehalten werden. Hier ist ein Beispiel, das eine Reihe von Komponenten in der richtigen Reihenfolge auf einer Fertigungslinie platziert:
%Vor% Hier stellt <T>
sicher, dass T[]
und List<T>
denselben Typ T
und nicht (sagen wir), Integer[]
und List<string>
enthalten.
Tags und Links java constructor generics