Warum sollten wir den Konstruktor im Unterricht privat machen? Da der Konstruktor immer öffentlich sein muss.
134
Einige Gründe, aus denen Sie möglicherweise einen privaten Konstruktor benötigen:
final
auf Klassenebene setzen. Das Setzen eines privaten Konstruktors ist aus diesem Grund so gut wie nutzlos.final
. Dies hat Sun für die String-Klasse getan und einen vernünftigen Teil der API, der nicht erweitert werden sollte.Durch die Bereitstellung eines privaten Konstruktors verhindern Sie, dass Klasseninstanzen an einem anderen Ort als dieser Klasse erstellt werden. Es gibt mehrere Anwendungsfälle für die Bereitstellung eines solchen Konstruktors.
A. Ihre Klasseninstanzen werden in einer
static
Methode erstellt. Diestatic
Methode wird dann als deklariertpublic
.B. Ihre Klasse ist ein Singleton . Dies bedeutet, dass nicht mehr als eine Instanz Ihrer Klasse im Programm vorhanden ist.
C. (Gilt nur für den kommenden C ++ 0x-Standard) Sie haben mehrere Konstruktoren. Einige von ihnen sind deklariert
public
, andereprivate
. Um die Codegröße zu reduzieren, rufen öffentliche Konstruktoren private Konstruktoren auf, die wiederum die ganze Arbeit erledigen. Ihrepublic
Konstruktoren werden daher als delegierende Konstruktoren bezeichnet:D. Sie möchten das Kopieren von Objekten einschränken (z. B. aufgrund der Verwendung einer gemeinsam genutzten Ressource):
E. Ihre Klasse ist eine Utility-Klasse . Das heißt, es enthält nur
static
Mitglieder. In diesem Fall darf niemals eine Objektinstanz im Programm erstellt werden.quelle
Eine "Hintertür" verlassen, die es einer anderen Freundklasse / Funktion ermöglicht, ein Objekt auf eine Weise zu konstruieren, die dem Benutzer verboten ist. Ein Beispiel, das mir in den Sinn kommt, wäre ein Container, der einen Iterator (C ++) erstellt:
quelle
friend
wenn dies nicht gerechtfertigt ist - und es gibt viele Fälle, in denen dies eine schlechte Idee ist. Leider wurde die Nachricht zu gut aufgenommen, und viele Entwickler lernen die Sprache nie gut genug, um zu verstehen, dass die gelegentliche Verwendungfriend
nicht nur akzeptabel, sondern auch vorzuziehen ist . Ihr Beispiel war genau so ein Fall. Absichtliche starke Kopplung ist kein Verbrechen, sondern eine Entwurfsentscheidung.Jeder steckt in der Singleton-Sache fest, wow.
Andere Dinge:
quelle
Dies kann für einen Konstruktor sehr nützlich sein, der allgemeinen Code enthält. Private Konstruktoren können von anderen Konstruktoren mit 'this (...);' aufgerufen werden. Notation. Indem Sie den allgemeinen Initialisierungscode in einem privaten (oder geschützten) Konstruktor erstellen, machen Sie auch explizit klar, dass er nur während der Erstellung aufgerufen wird, was nicht der Fall ist, wenn es sich lediglich um eine Methode handelt:
quelle
In einigen Fällen möchten Sie möglicherweise keinen öffentlichen Konstruktor verwenden. Zum Beispiel, wenn Sie eine Singleton-Klasse möchten.
Wenn Sie eine Assembly schreiben, die von Drittanbietern verwendet wird, gibt es möglicherweise eine Reihe interner Klassen, die nur von Ihrer Assembly erstellt und nicht von Benutzern Ihrer Assembly instanziiert werden sollen.
quelle
Dadurch wird sichergestellt, dass Sie (die Klasse mit privatem Konstruktor) steuern, wie der Konstruktor aufgerufen wird.
Ein Beispiel: Eine statische Factory-Methode für die Klasse kann Objekte zurückgeben, wenn die Factory-Methode sie zuweist (z. B. eine Singleton-Factory).
quelle
Wir können auch einen privaten Konstruktor haben, um die Erstellung des Objekts nur durch eine bestimmte Klasse durchzuführen (aus Sicherheitsgründen).
Eine Möglichkeit, dies zu tun, besteht darin, eine Freundesklasse zu haben.
C ++ Beispiel:
Hinweis: Hinweis: Nur ClientClass (da es mit SecureClass befreundet ist) kann den Konstruktor von SecureClass aufrufen.
quelle
Hier sind einige der Verwendungen von privaten Konstruktoren:
quelle
Wenn Sie nicht möchten, dass Benutzer Instanzen dieser Klasse erstellen oder eine Klasse erstellen, die diese Klasse erbt, wie z. B. die
java.lang.math
gesamte Funktion in diesem Paketstatic
. Alle Funktionen können aufgerufen werden, ohne eine Instanz von zu erstellen. Dahermath
wird der Konstruktor als statisch angekündigt .quelle
Wenn es privat ist, können Sie es nicht aufrufen ==> Sie können die Klasse nicht instanziieren. In einigen Fällen nützlich, wie ein Singleton.
Es gibt eine Diskussion und einige weitere Beispiele hier .
quelle
Ich habe eine Frage von Ihnen gesehen, die sich mit demselben Thema befasst.
Wenn Sie den anderen nicht erlauben möchten, Instanzen zu erstellen, halten Sie den Konstruktor in einem begrenzten Bereich. Die praktische Anwendung (ein Beispiel) ist das Singleton-Muster.
quelle
Sie sollten den Konstruktor nicht privat machen. Zeitraum. Machen Sie es geschützt, damit Sie die Klasse bei Bedarf erweitern können.
Edit: Ich stehe dazu, egal wie viele Downvotes du darauf wirfst. Sie schneiden das Potenzial für zukünftige Entwicklungen des Codes ab. Wenn andere Benutzer oder Programmierer wirklich entschlossen sind, die Klasse zu erweitern, ändern sie einfach den Konstruktor in Quell- oder Bytecode-Schutz. Sie werden nichts anderes erreicht haben, als ihr Leben ein wenig schwieriger zu machen. Fügen Sie eine Warnung in die Kommentare Ihres Konstruktors ein und belassen Sie sie dabei.
Wenn es sich um eine Utility-Klasse handelt, besteht die einfachere, korrektere und elegantere Lösung darin, die gesamte Klasse als "statisch endgültig" zu markieren, um eine Erweiterung zu verhindern. Es nützt nichts, den Konstruktor nur als privat zu markieren. Ein wirklich entschlossener Benutzer kann immer Reflexion verwenden, um den Konstruktor zu erhalten.
Gültige Verwendungen:
protected
Konstruktors besteht darin, die Verwendung statischer Factory-Methoden zu erzwingen, mit denen Sie die Instanziierung einschränken oder teure Ressourcen (DB-Verbindungen, native Ressourcen) bündeln und wiederverwenden können.quelle
Der Konstruktor ist für einen bestimmten Zweck privat, z. B. wenn Sie Singleton implementieren oder die Anzahl der Objekte einer Klasse begrenzen müssen. Zum Beispiel müssen wir in der Singleton-Implementierung den Konstruktor privat machen
Wenn Sie die Objekterstellung auf 10 beschränken möchten, verwenden Sie Folgendes
Vielen Dank
quelle
Sie können mehr als einen Konstruktor haben. C ++ bietet einen Standardkonstruktor und einen Standardkopierkonstruktor, wenn Sie keinen explizit angeben. Angenommen, Sie haben eine Klasse, die nur mit einem parametrisierten Konstruktor erstellt werden kann. Vielleicht hat es Variablen initialisiert. Wenn ein Benutzer diese Klasse dann ohne diesen Konstruktor verwendet, kann dies zu Problemen führen. Eine gute allgemeine Regel: Wenn die Standardimplementierung nicht gültig ist, machen Sie sowohl den Standardkonstruktor als auch den Kopierkonstruktor privat und geben Sie keine Implementierung an:
Verwenden Sie den Compiler, um zu verhindern, dass Benutzer das Objekt mit den ungültigen Standardkonstruktoren verwenden.
quelle
Wenn Sie aus Effective Java zitieren , können Sie eine Klasse mit privatem Konstruktor haben, um eine Dienstprogrammklasse zu haben, die Konstanten definiert (als statische Endfelder).
( BEARBEITEN: Gemäß dem Kommentar ist dies möglicherweise nur mit Java anwendbar. Ich weiß nicht, ob dieses Konstrukt in anderen OO-Sprachen anwendbar ist / benötigt wird (z. B. C ++).)
Ein Beispiel wie folgt:
EDIT_1 : Auch hier gilt die folgende Erklärung in Java: (und unter Bezugnahme auf das Buch Effective Java )
Eine Instanziierung einer Utility-Klasse wie die folgende ist zwar nicht schädlich, hat jedoch keinen Zweck, da sie nicht für die Instanziierung ausgelegt ist.
Angenommen, es gibt keinen privaten Konstruktor für Klassenkonstanten. Ein Codeblock wie unten ist gültig, vermittelt jedoch nicht besser die Absicht des Benutzers der Constants-Klasse
im Gegensatz zu Code wie
Ich denke auch, dass ein privater Konstrukteur die Absicht des Designers der Constants (sagen wir) Klasse besser vermittelt.
Java bietet einen standardmäßigen parameterlosen öffentlichen Konstruktor, wenn kein Konstruktor bereitgestellt wird und wenn Sie die Instanziierung verhindern möchten, wird ein privater Konstruktor benötigt.
Man kann eine statische Klasse der obersten Ebene nicht markieren und sogar eine letzte Klasse kann instanziiert werden.
quelle
Utility-Klassen können private Konstruktoren haben. Benutzer der Klassen sollten diese Klassen nicht instanziieren können:
quelle
Möglicherweise möchten Sie verhindern, dass eine Klasse frei instanziiert wird. Sehen Sie sich das Singleton-Entwurfsmuster als Beispiel an. Um die Einzigartigkeit zu gewährleisten, darf niemand eine Instanz davon erstellen :-)
quelle
Eine der wichtigsten Anwendungen ist die SingleTon-Klasse
Es ist auch geeignet, wenn Ihre Klasse nur statische Methoden hat. dh niemand muss Ihre Klasse instanziieren
quelle
Es ist wirklich ein offensichtlicher Grund: Sie möchten ein Objekt erstellen, aber es ist nicht praktisch, dies (in Bezug auf die Schnittstelle) innerhalb des Konstruktors zu tun.
Das
Factory
Beispiel ist ganz offensichtlich, lassen Sie mich dieNamed Constructor
Redewendung demonstrieren .Angenommen, ich habe eine Klasse,
Complex
die eine komplexe Zahl darstellen kann.Die Frage ist: Erwartet der Konstruktor den Real- und Imaginärteil oder erwartet er die Norm und den Winkel (Polarkoordinaten)?
Ich kann die Benutzeroberfläche ändern, um es einfacher zu machen:
Dies wird als
Named Constructor
Redewendung bezeichnet: Die Klasse kann nur von Grund auf neu erstellt werden, indem explizit angegeben wird, welchen Konstruktor wir verwenden möchten.Es ist ein Sonderfall vieler Bauweisen. Die Entwurfsmuster bieten eine gute Anzahl von Möglichkeiten , um Bauobjekt:
Builder
,Factory
,Abstract Factory
, ... und ein privater Konstruktor wird sichergestellt , dass der Benutzer richtig eingeschränkt.quelle
Neben den bekannteren Verwendungen…
So implementieren Sie das Methodenobjektmuster , das ich wie folgt zusammenfassen würde:
Wenn Sie eine Funktion mithilfe eines Objekts implementieren möchten und das Objekt außerhalb einer einmaligen Berechnung (durch einen Methodenaufruf) nicht nützlich ist, verfügen Sie über ein Wegwerfobjekt . Sie können die Objekterstellung und den Methodenaufruf in einer statischen Methode kapseln, um dieses allgemeine Anti-Pattern zu verhindern:
… Durch einen (namengebundenen) Funktionsaufruf ersetzen:
Der Anrufer muss niemals wissen oder sich darum kümmern, dass Sie ein Objekt intern verwenden, eine sauberere Benutzeroberfläche erhalten und verhindern, dass Müll vom Objekt herumhängt oder das Objekt falsch verwendet wird.
Zum Beispiel, wenn Sie eine Berechnung über Methoden zu brechen
foo
,bar
undzork
zum Beispiel auf Aktien Zustand ohne viele Werte passieren zu müssen in und aus Funktionen, man könnte es wie folgt implementieren:Dieses Methodenobjektmuster finden Sie in Smalltalk Best Practice Patterns , Kent Beck, S. 34–37. Dort ist es der letzte Schritt eines Refactoring-Musters und endet mit:
Dies unterscheidet sich erheblich von den anderen Beispielen hier: Die Klasse ist instanziierbar (im Gegensatz zu einer Utility-Klasse), aber die Instanzen sind privat (im Gegensatz zu Factory-Methoden, einschließlich Singletons usw.) und können auf dem Stapel leben, da sie niemals entkommen.
Dieses Muster ist sehr nützlich bei Bottom-Up-OOP, bei dem Objekte verwendet werden, um die Implementierung auf niedriger Ebene zu vereinfachen, aber nicht unbedingt extern verfügbar gemacht werden, und steht im Gegensatz zu dem Top-Down-OOP, das häufig dargestellt wird und mit Schnittstellen auf hoher Ebene beginnt.
quelle
Manchmal ist es nützlich, wenn Sie steuern möchten, wie und wann (und wie viele) Instanzen eines Objekts erstellt werden.
Unter anderem in Mustern verwendet:
quelle
Die Verwendung privater Konstruktoren könnte auch dazu dienen, die Lesbarkeit / Wartbarkeit angesichts des domänengesteuerten Designs zu verbessern. Aus "Microsoft .NET - Erstellen von Anwendungen für Unternehmen, 2. Ausgabe":
Zitat: "Hier gibt es zwei Probleme. Erstens kann man beim Betrachten des Codes kaum erraten, was los ist. Eine Instanz von OrderRequest wird erstellt, aber warum und mit welchen Daten? Was ist 1234? Dies führt zum zweiten Problem: Sie verletzen die allgegenwärtige Sprache des begrenzten Kontexts. Die Sprache sagt wahrscheinlich Folgendes aus: Ein Kunde kann eine Bestellanfrage stellen und darf eine Kauf-ID angeben. Wenn dies der Fall ist, können Sie hier eine neue OrderRequest-Instanz abrufen : "
wo
Ich befürworte dies nicht für jede einzelne Klasse, aber für das obige DDD-Szenario halte ich es für absolut sinnvoll, eine direkte Erstellung eines neuen Objekts zu verhindern.
quelle