Ich habe gesucht und kenne den theoretischen Unterschied.
- public - Jede Klasse / Funktion kann auf die Methode / Eigenschaft zugreifen.
- protected - Nur diese Klasse und alle Unterklassen dürfen auf die Methode / Eigenschaft zugreifen.
- privat - Nur diese Klasse kann auf die Methode / Eigenschaft zugreifen. Es wird nicht einmal vererbt.
Das ist alles in Ordnung und gut, die Frage ist, was ist der praktische Unterschied zwischen ihnen? Wann würden Sie verwenden private
und wann würden Sie verwenden protected
? Gibt es eine Standard- oder akzeptable bewährte Methode für diese?
Um das Konzept der Vererbung und des Polymorphismus beizubehalten, verwende ich bis jetzt public
alles, auf das von außen zugegriffen werden soll (wie Konstruktoren und Hauptklassenfunktionen), und protected
interne Methoden (Logik, Hilfsmethoden usw.). Bin ich auf dem richtigen Weg?
(Beachten Sie, dass diese Frage für mich ist, aber auch zum späteren Nachschlagen, da ich eine Frage wie diese SO nicht gesehen habe).
oop
language-agnostic
coding-style
Madaras Geist
quelle
quelle
internal
in C # -Sprache, der die Zugriffsebene einer Klasse oder ihrer Mitglieder innerhalb einer physischen Assembly einschränkt. Ich bin mir jedoch nicht sicher über die Unterstützung oder ähnliches in anderen Sprachen.Antworten:
Nein, Sie sind nicht auf dem richtigen Weg. Eine gute Faustregel lautet: Machen Sie alles so privat wie möglich. Dadurch wird Ihre Klasse gekapselter und die Interna der Klasse können geändert werden, ohne dass sich dies auf den Code Ihrer Klasse auswirkt.
Wenn Sie Ihre Klasse so gestalten, dass sie vererbbar ist, wählen Sie sorgfältig aus, was von Unterklassen überschrieben und zugänglich sein kann, und machen Sie diese geschützt (und endgültig, wenn Sie von Java sprechen möchten, wenn Sie sie zugänglich, aber nicht überschreibbar machen möchten). Beachten Sie jedoch, dass dieses Feld oder diese Methode Teil der öffentlichen API der Klasse ist und möglicherweise später nicht geändert wird, ohne Unterklassen zu beschädigen, sobald Sie akzeptieren, dass Unterklassen Ihrer Klasse vorhanden sind und ein geschütztes Feld oder eine geschützte Methode vorhanden ist.
Eine Klasse, die nicht vererbt werden soll, sollte endgültig gemacht werden (in Java). Sie können einige Zugriffsregeln (privat bis geschützt, endgültig bis nicht endgültig) für Unit-Tests lockern, sie dann aber dokumentieren und klarstellen, dass die Methode zwar geschützt ist, aber nicht überschrieben werden darf.
quelle
private
vsprotected
Wann soll eine Eigenschaft vererbt werden und wann nicht? Ich kann nicht wirklich sagen, ob ein Benutzer manchmal in der Zukunft meine Klasse nehmen und erweitern möchte ...Lassen Sie mich dies vorwegnehmen, indem Sie sagen, dass ich hier hauptsächlich über den Methodenzugriff spreche und in etwas geringerem Maße Klassen als endgültig und nicht als Mitgliederzugriff markiere .
Die alte Weisheit
machte Sinn in Tagen, als es geschrieben wurde, bevor Open Source den Entwicklerbibliotheksraum und VCS / Dependency mgmt dominierte. wurde dank Github, Maven usw. hyperkooperativ. Damals gab es auch Geld zu verdienen, indem die Art und Weise, wie eine Bibliothek genutzt werden konnte, eingeschränkt wurde. Ich habe wahrscheinlich die ersten 8 oder 9 Jahre meiner Karriere damit verbracht, mich strikt an diese "Best Practice" zu halten.
Heute halte ich es für einen schlechten Rat. Manchmal gibt es ein vernünftiges Argument, um eine Methode als privat oder als Klassenfinale zu markieren, aber es ist äußerst selten, und selbst dann verbessert es wahrscheinlich nichts.
Hast du jemals:
Dies sind die drei größten Rationalisierungen, die ich für das standardmäßige Markieren von Methoden gehört habe:
Rationalisierung Nr. 1: Es ist unsicher und es gibt keinen Grund, eine bestimmte Methode zu überschreiben
Ich kann nicht zählen, wie oft ich mich geirrt habe, ob es jemals notwendig sein wird, eine bestimmte von mir geschriebene Methode zu überschreiben. Nachdem ich an mehreren populären Open-Source-Bibliotheken gearbeitet hatte, lernte ich auf die harte Tour die wahren Kosten für das Markieren von privaten Dingen. Oft entfällt die einzig praktikable Lösung für unvorhergesehene Probleme oder Anwendungsfälle. Umgekehrt habe ich es in mehr als 16 Jahren beruflicher Entwicklung nie bereut, eine aus Gründen der API-Sicherheit geschützte statt private Methode markiert zu haben. Wenn ein Entwickler eine Klasse erweitert und eine Methode überschreibt, sagt er bewusst: "Ich weiß, was ich tue." und aus Gründen der Produktivität sollte das ausreichen. Zeitraum. Wenn es gefährlich ist, notieren Sie es in der Klasse / Methode Javadocs, schlagen Sie die Tür nicht einfach blind zu.
Standardmäßig geschützte Markierungsmethoden sind eine Abschwächung für eines der Hauptprobleme in der modernen SW-Entwicklung: ein Versagen der Vorstellungskraft.
Rationalisierung Nr. 2: Sie hält die öffentliche API / Javadocs sauber
Dieser ist vernünftiger und je nach Zielgruppe vielleicht sogar das Richtige, aber es lohnt sich zu überlegen, wie hoch die Kosten für die "Sauberkeit" der API tatsächlich sind: Erweiterbarkeit. Aus den oben genannten Gründen ist es wahrscheinlich sinnvoller, für alle Fälle standardmäßig geschützte Dinge zu markieren.
Rationalisierung Nr. 3: Meine Software ist kommerziell und ich muss ihre Verwendung einschränken.
Dies ist auch vernünftig, aber als Verbraucher würde ich mich jedes Mal für den weniger restriktiven Wettbewerber entscheiden (vorausgesetzt, es bestehen keine signifikanten Qualitätsunterschiede).
Sag niemals nie
Ich sage nicht, niemals Methoden als privat zu markieren. Ich sage, die bessere Faustregel lautet: "Methoden schützen, es sei denn, es gibt einen guten Grund, dies nicht zu tun".
Dieser Rat ist am besten für diejenigen geeignet, die an Bibliotheken oder größeren Projekten arbeiten, die in Module unterteilt wurden. Bei kleineren oder monolithischeren Projekten spielt dies keine Rolle, da Sie ohnehin den gesamten Code kontrollieren und es einfach ist, die Zugriffsebene Ihres Codes zu ändern, wenn Sie ihn benötigen. Selbst dann würde ich immer noch den gleichen Rat geben :-)
quelle
Rationalization # 1
- Wenn ich etwas als geschützt markiere, entscheide ich mich ausdrücklich dafür, da ich der Meinung bin, dass dieses Verhalten nicht endgültig ist und möglicherweise ein Fall ist, in dem meine Kinderklassen es überschreiben möchten. Wenn ich mir nicht so sicher bin, möchte ich es standardmäßig privat machen. Insbesondere in einer Sprache wie C #, in der eine Methode standardmäßig nicht virtuell bleibt, macht es keinen Sinn, nur einen geschützten Zugriffsspezifizierer hinzuzufügen. Sie müssen sowohlvirtual
als auchprotected
Schlüsselwörter hinzufügen , um Ihre Absicht sehr deutlich zu machen. Außerdem bevorzugen die Leute die Assoziation gegenüber der Vererbung,protected
da die Standardeinstellung schwer zu erkennen istHör auf, private Felder zu missbrauchen !!!
Die Kommentare hier scheinen die Verwendung privater Felder überwiegend zu unterstützen. Nun, dann habe ich etwas anderes zu sagen.
Sind private Felder grundsätzlich gut? Ja. Aber zu sagen, dass eine goldene Regel darin besteht, alles privat zu machen, wenn Sie sich nicht sicher sind, ist definitiv falsch ! Sie werden das Problem erst sehen, wenn Sie auf eines stoßen. Meiner Meinung nach sollten Sie Felder als geschützt markieren, wenn Sie sich nicht sicher sind .
Es gibt zwei Fälle, in denen Sie eine Klasse erweitern möchten:
An privaten Feldern ist im ersten Fall nichts auszusetzen. Die Tatsache, dass Leute private Felder missbrauchen , macht es so frustrierend, wenn Sie herausfinden, dass Sie Scheiße nicht ändern können.
Stellen Sie sich eine einfache Bibliothek vor, die Autos modelliert:
Der Bibliotheksautor dachte: Es gibt keinen Grund, warum die Benutzer meiner Bibliothek auf die Implementierungsdetails von
assembleCar()
richtig zugreifen müssen . Markieren wir die Schraube als privat.Nun, der Autor ist falsch. Wenn Sie nur die
assembleCar()
Methode ändern möchten, ohne die gesamte Klasse in Ihr Paket zu kopieren, haben Sie kein Glück. Sie müssen Ihr eigenesscrew
Feld neu schreiben . Nehmen wir an, dieses Auto verwendet ein Dutzend Schrauben, und jede von ihnen enthält einen nicht trivialen Initialisierungscode in verschiedenen privaten Methoden, und diese Schrauben sind alle als privat gekennzeichnet. An diesem Punkt beginnt es zu saugen.Ja, Sie können mit mir argumentieren, dass der Bibliotheksautor besseren Code hätte schreiben können, sodass an privaten Feldern nichts auszusetzen ist . Ich behaupte nicht, dass das private Feld ein Problem mit OOP ist . Es ist ein Problem, wenn Leute sie benutzen.
Die Moral der Geschichte lautet: Wenn Sie eine Bibliothek schreiben, wissen Sie nie, ob Ihre Benutzer auf ein bestimmtes Feld zugreifen möchten. Wenn Sie sich nicht sicher sind, markieren Sie es,
protected
damit alle später glücklicher sind. Zumindest nicht das private Feld missbrauchen .Ich unterstütze Nicks Antwort sehr.
quelle
Ich habe vor einiger Zeit einen Artikel gelesen, in dem es darum ging, jede Klasse so weit wie möglich zu sperren. Machen Sie alles endgültig und privat, es sei denn, Sie müssen sofort einige Daten oder Funktionen der Außenwelt zugänglich machen. Es ist immer einfach, den Geltungsbereich zu erweitern, um später zulässiger zu werden, aber nicht umgekehrt. Betrachten wir zuerst so viele Dinge wie möglich zu machen ,
final
die zwischen der Wahl machenprivate
undprotected
viel einfacher.Wenn Sie eine Abschlussklasse haben, machen Sie alles privat, es sei denn, die Welt braucht unbedingt etwas - machen Sie es öffentlich.
Wenn Sie eine Klasse mit Unterklassen haben, überprüfen Sie alle Eigenschaften und Methoden sorgfältig. Überlegen Sie zunächst, ob Sie diese Eigenschaft / Methode überhaupt Unterklassen zugänglich machen möchten. Wenn Sie dies tun, prüfen Sie, ob eine Unterklasse Ihr Objekt zerstören kann, wenn sie den Eigenschaftswert oder die Methodenimplementierung beim Überschreiben durcheinander bringt. Wenn es möglich ist und Sie die Eigenschaft / Methode Ihrer Klasse auch vor Unterklassen schützen möchten (klingt ironisch, ich weiß), machen Sie sie privat. Ansonsten machen Sie es geschützt.
Haftungsausschluss: Ich programmiere nicht viel in Java :)
quelle
final class
in Java ist eine Klasse, von der nicht geerbt werden kann. Afinal method
ist nicht virtuell, dh nicht von einer Unterklasse überschreibbar (Java-Methoden sind standardmäßig virtuell). Afinal field/parameter/variable
ist eine unveränderliche Variablenreferenz (in dem Sinne, dass sie nach der Initialisierung nicht mehr geändert werden kann).Wann würden Sie verwenden
private
und wann würden Sie verwendenprotected
?Private Vererbung kann eher als Beziehung als als IS-A- Beziehung implementiert betrachtet werden . Einfach ausgedrückt, die externe Schnittstelle der ererbenden Klasse hat keine (sichtbare) Beziehung zur geerbten Klasse. Sie verwendet die Vererbung nur, um eine ähnliche Funktionalität zu implementieren, die die Basisklasse bereitstellt.
private
Im Gegensatz zur privaten Vererbung ist die geschützte Vererbung eine eingeschränkte Form der Vererbung, bei der die abgeleitete Klasse IS-A der Basisklasse ist und der Zugriff der abgeleiteten Mitglieder nur auf die abgeleitete Klasse beschränkt werden soll.
quelle
Nun, es geht nur um die Kapselung, wenn die Paybill-Klassen die Abrechnung von Zahlungen abwickeln, dann in der Produktklasse, warum sollte der gesamte Abrechnungsprozess benötigt werden, dh die Zahlungsmethode, wie zu zahlen ist, wo zu zahlen ist. Lassen Sie also nur das, was für andere Klassen und Objekte verwendet wird nichts weiter als diese Öffentlichkeit für diejenigen, die auch andere Klassen verwenden würden, geschützt für diese Begrenzung nur für die Erweiterung von Klassen. Da Sie Madara Uchiha sind, ist das Private so, wie
"limboo"
Sie es sehen können (Sie unterrichten nur eine Klasse).quelle