Warum brauchen wir private Variablen?


210

Warum brauchen wir private Variablen in Klassen?

Jedes Buch über Programmierung, das ich gelesen habe, besagt, dass dies eine private Variable ist, so definiert man es, hört aber dort auf.

Der Wortlaut dieser Erklärungen kam mir immer so vor, als hätten wir wirklich eine Vertrauenskrise in unseren Beruf. Die Erklärungen klangen immer so, als würden andere Programmierer unseren Code durcheinander bringen. Es gibt jedoch viele Programmiersprachen ohne private Variablen.

  1. Was verhindern private Variablen?

  2. Wie entscheiden Sie, ob eine bestimmte Immobilie privat sein soll oder nicht? Wenn standardmäßig jedes Feld privat sein SOLLTE, warum gibt es dann öffentliche Datenelemente in einer Klasse?

  3. Unter welchen Umständen sollte eine Variable veröffentlicht werden?


9
Ihre Frage klingt sehr sprachunabhängig, aber Sie haben sie als Java und C ++ markiert. Wenn Sie sich für Perspektiven von außerhalb dieser beiden Sprachen interessieren, sollten Sie dies wahrscheinlich sagen.
James

8
Für den Datensatz erhöht das Erstellen einer privaten Methode nicht die "Sicherheit". Andere Teile Ihrer Anwendung können weiterhin über Reflection auf private Mitglieder zugreifen.
kba

3
Die Verwendung und der Unterschied von privaten und öffentlichen Variablen und warum wir sie haben, können nur im Kontext allgemeiner objektorientierter Prinzipien verstanden werden. Es kann nicht separat verstanden werden. Sie müssen es wahrscheinlich aus dieser Perspektive betrachten, die Dinge könnten klarer werden.
Nazar Merza

1
?

3
Wenn Sie jemanden mit einem Sicherheitsgurt im Auto erwischen, sollten Sie ihm den Führerschein wegnehmen, da er offensichtlich seinen eigenen Fahrfähigkeiten nicht vertraut.
gnasher729

Antworten:


307

Es geht nicht so sehr um Vertrauen, sondern darum, mit Komplexität umzugehen.

Auf ein öffentliches Mitglied kann von außerhalb der Klasse zugegriffen werden, was aus praktischen Erwägungen "potenziell überall" bedeutet. Wenn in einem öffentlichen Bereich etwas schief geht, kann der Täter überall sein, und um den Fehler aufzuspüren, müssen Sie sich möglicherweise eine ganze Menge Code ansehen.

Im Gegensatz dazu kann auf ein privates Mitglied nur innerhalb derselben Klasse zugegriffen werden. Wenn also etwas schief geht, gibt es normalerweise nur eine Quelldatei, auf die zugegriffen werden kann. Wenn Ihr Projekt eine Million Codezeilen enthält, Ihre Klassen jedoch klein gehalten werden, kann dies den Aufwand für die Fehlerverfolgung um den Faktor 1000 verringern.

Ein weiterer Vorteil betrifft das Konzept der "Kopplung". Ein öffentliches Mitglied meiner Klasse , Adie von einer anderen Klasse verwendet wird , Bstellt eine Abhängigkeit: Wenn Sie ändern min A, müssen Sie auch Verwendungen von Check min B. Schlimmer noch, nichts in der Klasse Asagt dir, wo mbenutzt wird, also musst du wieder die gesamte Codebasis durchsuchen; Wenn es sich um eine Bibliothek handelt, die Sie schreiben, müssen Sie sogar sicherstellen, dass der Code draußen istIhr Projekt bricht nicht wegen Ihrer Änderung. In der Praxis neigen Bibliotheken dazu, so lange wie möglich an ihren ursprünglichen Methodensignaturen festzuhalten, egal wie schmerzhaft sie sind, und dann mit einem Hauptversionsupdate eine Reihe wichtiger Änderungen einzuführen. Im Gegensatz dazu können Sie bei privaten Mitgliedern Abhängigkeiten sofort ausschließen. Auf sie kann nicht von außen zugegriffen werden, sodass alle Abhängigkeiten in der Klasse enthalten sind.

In diesem Zusammenhang beziehen "andere Programmierer" Ihre Zukunft und Ihre Vergangenheit mit ein. Es besteht die Möglichkeit , dass Sie jetzt wissen, dass Sie dieses Ding X nicht mit Ihrer Variablen Y ausführen sollten, aber Sie müssen drei Monate später vergessen haben, wenn ein Kunde dringend eine Funktion implementieren muss, und Sie fragen sich, warum Sie X-Pausen ausführen Y auf dunkle Weise.

Also, wenn Sie Dinge privat machen sollten: Ich würde sagen, machen Sie alles standardmäßig privat und machen Sie dann nur die Teile verfügbar, die unbedingt öffentlich sein müssen. Je mehr Sie privat machen können, desto besser.


24
+1, um den Kern des Problems zu lösen, obwohl ich persönlich der Meinung war, dass mein Code einfacher zu warten ist, als ich aufgehört habe, durch Rahmen zu gehen, nur um sicherzustellen, dass eine häufig verwendete Variable privat bleibt. Sicher, ein Fehler kann in der Zukunft auftreten, aber es sind 60 Zeilen weniger Code zum Durchsieben und weniger Variablen und Funktionen zum Booten;)
Jeffrey Sweeney

48
Das Allerheiligste am modernen Rechnen ist, die Komplexität gering zu halten.

1
Ich möchte immer sagen, dass ein Teil des Debuggens nicht nur direkt auf "was schief gelaufen ist" abzielt, sondern den Umweg macht, "was nicht schief gelaufen ist" und meine Untersuchung auf das konzentriert, was noch übrig ist. Wenn ich den Compiler dazu bringen kann, mich mit Tools wie privaten Variablen zu unterstützen, um zu definieren, "was möglicherweise nicht aufgetreten ist", spart mir das eine Menge Zeit. Nur in den seltenen Fällen, in denen ich nachweise, dass das, was schief gelaufen ist, nicht eingetreten ist, muss ich mich mit den erschreckenderen Annahmen auseinandersetzen, wie etwa einem Pufferüberlauf, der meine privaten Daten überschreibt.
Cort Ammon

2
Genau das. Wenn Leute hören, "Informationen versteckt", denken sie, dass sie private Variablen für Dinge wie Verschlüsselungsschlüssel, Datenbankanmeldeinformationen usw. verwenden sollten
Wayne Werner

2
@AdamZerner siehe "Erzählen, nicht fragen" ( martinfowler.com/bliki/TellDontAsk.html ), ob Getter / Setter an erster Stelle stehen - aber ansonsten ja, da Sie die interne Darstellung des Werts jederzeit ändern können sollten das hättest du wohl gerne. Wie immer gibt es Ausnahmen ... (zB DTOs)
doubleYou

111

Private Variablen verhindern, dass Personen von bestimmten Teilen Ihres Codes abhängig sind. Angenommen, Sie möchten eine Datenstruktur implementieren. Sie möchten, dass es den Benutzern Ihrer Datenstruktur egal ist, wie Sie sie implementiert haben, sondern dass sie die Implementierung nur über Ihre genau definierte Schnittstelle verwenden. Der Grund dafür ist, dass Sie es jederzeit ändern können, wenn niemand von Ihrer Implementierung abhängig ist. Beispielsweise können Sie die Back-End-Implementierung ändern, um die Leistung zu verbessern. Alle anderen Entwickler, die von Ihren Implementierungen abhängig sind, brechen ab, während die Benutzer der Benutzeroberfläche in Ordnung sind. Die Flexibilität, Implementierungen zu ändern, ohne die Klassenbenutzer zu beeinflussen, ist ein großer Vorteil, den die Verwendung privater Variablen (und allgemeiner die Kapselung ) bietet.

Es ist auch nicht wirklich eine "Vertrauenskrise". Wenn Sie ein Datenelement veröffentlichen, können Sie nicht sicherstellen, dass niemand darauf angewiesen ist. Es ist oft sehr praktisch, sich auf eine implementierungsspezifische Variable zu verlassen, anstatt die öffentliche Schnittstelle zu durchlaufen, insbesondere in der Hitze einer Frist. Außerdem werden Entwickler nicht immer erkennen, dass sie von etwas abhängig sind, das sich ändern könnte.

Ich hoffe, diese Art beantwortet Ihre anderen Fragen. Alle Implementierungsdetails sollten privat sein, und der öffentliche Teil sollte eine kleine, präzise und gut definierte Schnittstelle für die Verwendung Ihrer Klasse sein.


24
IMO geht es auch um die Kommunikation zwischen dem lib-Autor und dem lib-Konsumenten. Öffentliche Schnittstelle ist wie „verwendet diese“ und Gemeinen sind wie „nicht verwenden , dass“ außer dass in Java, Sie wirklich nicht zufällig verwenden können , wenn es so privat ist es sicherer und klarer auf diese Weise.
Chakrit

5
@chakrit und andere: Beachten Sie, dass diejenigen, die wirklich keine Lust haben, Ihre privaten Felder und Methoden zu verwenden, dies tun können (über Reflektion). privateist weniger als "nicht in erster Linie für die Sicherheit", es bietet keine "Sicherheit" zu sprechen. Es ist nur ein starker Hinweis (über den Compiler übermittelt), nicht darauf zuzugreifen.

@delnan Beachten Sie den Satz "durch Zufall" Ja, vielleicht sollte ich klarer sein.
Chakrit

@chakrit Ja, ich wollte nicht implizieren, dass du falsch lagst. Ich wollte nur diesen Punkt fördern.

1
@delnan: Private Felder bieten in einigen Sprachen bestimmte Sicherheitsfunktionen. Siehe beispielsweise Eric Lipperts Antwort auf " Dienen die Zugriffsebenen und Modifikatoren (privat, versiegelt usw.) in C # einem Sicherheitszweck?" .
Brian

25

Das Schlüsselwort lautet hier Encapsulation . In OOP möchten Sie private Variablen verwenden, um eine ordnungsgemäße Kapselung Ihrer Objekte / Klassen zu erzwingen.

Während andere Programmierer nicht darauf aus sind, Sie zu erreichen, interagieren sie mit Ihrem Code. Wenn Sie eine Variable nicht als privat kennzeichnen, verweisen sie möglicherweise in ihrem eigenen Code darauf, ohne dass dies Schaden anrichten möchte. Wenn Sie jedoch zu Ihrer Klasse zurückkehren und etwas ändern müssen, wissen Sie nicht mehr, wer welche Variable wo verwendet. Das Ziel der Kapselung besteht darin, die externe Schnittstelle der Klasse explizit zu machen, sodass Sie wissen, dass nur diese (normalerweise) Methoden von anderen verwendet wurden.

  1. Daher stellen private Variablen sicher, dass die entsprechende Variable nur in der definierenden Klasse verbleibt. Wenn Sie es ändern müssen, ist die Änderung für die Klasse selbst lokal.

  2. In traditionellen Sprachen wie C ++ oder Java machen Sie normalerweise alles privat und nur für entsprechende Getter und Setter zugänglich. Keine Notwendigkeit, wirklich viel zu entscheiden.

  3. Manchmal, z. In einer C ++ - Struktur benötigen Sie eine Klasse nur, um mehrere Dinge zu gruppieren. Betrachten Sie zum Beispiel eine Vector-Klasse, die nur ein xund ein yAttribut hat. In diesen Fällen können Sie den direkten Zugriff auf diese Attribute zulassen, indem Sie sie für öffentlich erklären. Insbesondere ist es Ihnen egal, ob ein Code außerhalb ein Objekt Ihrer Klasse durch direktes Schreiben neuer Werte in xoder ändert y.

Beachten Sie außerdem, dass diese Angelegenheit in anderen Sprachen als geringfügig anders angesehen wird. Beispielsweise betonen Sprachen, die stark in der funktionalen Programmierung verwurzelt sind, die Unveränderlichkeit von Daten, dh Datenwerte können überhaupt nicht geändert werden. In solchen Fällen müssen Sie sich nicht darum kümmern, was andere Programmierer (oder vielmehr deren Code) mit Ihren Daten tun. Sie können einfach nichts tun, was sich auf Ihren Code auswirken könnte, da alle Daten unveränderlich sind.

In diesen Sprachen erhalten Sie daher ein sogenanntes einheitliches Zugriffsprinzip , bei dem bewusst keine Methoden wie Getter und Setter unterschieden werden, sondern direkt auf die Variable / Funktion zugegriffen werden kann. Sie können also sagen, dass private Deklarationen in objektorientierten Szenarien sehr viel beliebter sind.

Dies zeigt auch, wie Sie durch die Erweiterung Ihres Wissens um andere Bereiche vorhandene Konzepte auf völlig neue Weise betrachten können.


1
+1 "Während andere Programmierer nicht darauf aus sind, Sie zu erreichen, interagieren sie mit Ihrem Code." Programmierer, die Ihren Code verwenden, sind nicht von Natur aus böse. Indem Sie private Variablen verwenden, stellen Sie sicher, dass sie (und Sie in Zukunft) mit dem Code nicht verletzt werden. Es hilft Ihnen auch, eine bessere API zu entwerfen und zu dokumentieren.
Szalski

7

Private Variablen stellen sicher, dass spätere Verweise außerhalb des Bereichs eines Objekts oder einer Funktion keine versehentlichen Auswirkungen auf andere Variablen haben. Bei großen Programmierprojekten können so viele interessante Probleme vermieden werden (die normalerweise nicht vom Compiler erfasst werden).

Prototypische Sprachen wie Javascript können es Benutzern beispielsweise ermöglichen, Variablen nach Belieben zu verputzen:

function SomeObject() {
    this.a = 2; //Public (well, actually protected) variable

    this.showA = function() {
        alert(this.a);
    }
}

//Some lines down...

var obj = new SomeObject();
obj.a = 3;
obj.showA(); //Will alert 3. Uh oh!

Wenn diese Variable privat wäre, könnte sie von außen nicht geändert werden:

function SomeObject() {
    var a = 2; //Private variable

    this.showA = function() {
        alert(a);
    }
}

//Some lines down...

var obj = new SomeObject();
obj.a = 3;
obj.showA(); //Will alert 2

Allerdings müssen nicht alle Variablen privat sein, und eine übermäßige Verwendung privater Variablen kann den Code tatsächlich umständlicher machen. Trivial Felder , die ernsthaft ein Objekt nicht beeinflussen nicht brauchen get()und set()Methoden.

Private Variablen vereinfachen auch das zukünftige Erweitern von Code, ohne dass umfangreiche Dokumentationen zu den Aufgaben der vielen öffentlichen Variablen erforderlich sind. Es besteht weniger die Gefahr, dass die Funktionalität versehentlich unterbrochen wird, wenn weniger Variablen überschrieben werden können.

Öffentliche Variablen sollten verwendet werden, wenn ein Objekt / eine Funktion auf andere Objekte / Funktionen zugreift, da private Variablen dies in der Regel nicht können. Möglicherweise haben Sie einige bis einige öffentliche Variablen, und es ist nicht schlecht, sie zu verwenden, wenn sie richtig verwendet werden.


Es ist nicht klar, warum die Warnung 3 ein "äh oh!" in diesem Fall. Vielleicht wollte der Programmierer das auch.
immibis

@immibis Vielleicht, und vielleicht hätte ich in der Antwort näher darauf eingehen sollen. Der Zugriff auf Eigenschaften kann jedoch die Tür für Verstöße gegen einige OOP-Prinzipien wie Open-Closed-Prinzip oder LoD öffnen, da Sie möglicherweise Implementierungsdetails preisgeben. Natürlich zu Ihrem Punkt kommt es darauf an, was die Eigenschaft genau ist. Die meisten Sprachen verwenden Objekte als Referenzen, und wenn Referenzen von Objekten weitergegeben werden und andere Entwickler die Eigenschaften stillschweigend ändern, kann es WIRKLICH schwierig sein, Fehler zu beheben. IMO ist es viel einfacher und erweiterbarer, mit Methoden zu arbeiten, wenn Sie eine Klasseninstanz haben.
Jeffrey Sweeney

7

Es gibt einige gute Antworten auf die Vorteile für zukünftige Betreuer und Benutzer einer Klasse. Das ursprüngliche Design bietet jedoch auch Vorteile. Es bietet eine klare Abgrenzung zwischen dem Ziel, die Dinge für sich selbst einfacher zu machen, und dem Ziel, die Dinge für den Klassenbenutzer einfacher zu machen. Wenn Sie zwischen öffentlich und privat wählen, signalisiert dies Ihrem Gehirn, in den einen oder anderen Modus zu wechseln, und Sie erhalten eine bessere API.

Es ist nicht so, dass Sprachen ohne Privatsphäre ein solches Design unmöglich machen, nur weniger wahrscheinlich. Anstatt dazu aufgefordert zu werden, so etwas zu schreiben foo.getBar(), neigen die Leute dazu zu denken, dass ein Getter nicht notwendig ist, weil es einfacher zu schreiben ist foo.bar, aber diese Entscheidung wird dann nicht wiederholt, wenn Sie später mit längeren Monstrositäten wie enden obj.container[baz].foo.bar. Programmierer, die noch nie in einer strengeren Sprache gearbeitet haben, sehen möglicherweise nicht einmal, was daran falsch ist.

Aus diesem Grund wird in Sprachen ohne Datenschutz häufig ein Namensstandard verwendet, der diesen simuliert, z. B. das Voranstellen eines Unterstrichs an alle "privaten" Mitglieder. Es ist ein nützliches Signal, auch wenn die Sprache es nicht erzwingt.


3

Alle Variablen sollten privat sein, es sei denn, sie müssen unbedingt öffentlich sein (was so gut wie nie der Fall ist, Sie sollten Eigenschaften / Getter und Setter verwenden).

Variablen stellen weitgehend den Status des Objekts bereit, und private Variablen verhindern, dass andere in das Objekt gelangen und den Status des Objekts ändern.


5
Eine viel zu enge Sicht auf das Thema. Es gibt Fälle, in denen der Zugang zum öffentlichen Feld
Roland Tepp

Man kann sicherlich Objekte entwerfen, deren Zustand nicht geändert werden kann (unveränderliche Objekte), aber dies ist keine allgemeine Regel, die auf alle Klassen angewendet wird. Nach meiner Erfahrung machen es die meisten Objekte anderen sehr leicht, den Status des Objekts zu ändern.
David K

1
@ DavidK Vielleicht wollte BBB damit sagen, dass "private Variablen andere daran hindern, in das Objekt einzusteigen und den Zustand des Objekts wahllos zu ändern". Öffentliche Methoden können den privaten Status des Objekts ändern, jedoch nur in einer Weise, die für die Funktionsweise des Objekts erforderlich und konsistent ist.
Max Nanasy

@Max Nanasy: Ja, man kann steuern, wie sich der Zustand ändert, wenn man nur Methoden in der öffentlichen Schnittstelle anbietet. Es kann beispielsweise eine Beziehung zwischen den Mitgliedern geben, die erfüllt sein muss, damit das Objekt "selbstkonsistent" ist, und Sie können zulassen, dass ein selbstkonsistenter Zustand nur in einen anderen selbstkonsistenten Zustand geändert wird. Wenn alle diese Variablen öffentlich sind, können Sie dies nicht erzwingen. Es kann aber auch Objekte geben, bei denen Sie keine Änderungen zulassen möchten. Daher ist es wichtig, klar zu machen, um welche dieser Dinge es sich handelt.
David K

2
  • Was verhindern private Variablen?

Es geht darum, zu verdeutlichen, welche Eigenschaften und Methoden die Schnittstelle sind und welche die eigentliche Kernfunktionalität darstellen. Öffentliche Methoden / Eigenschaften beziehen sich auf anderen Code, häufig auf den Code eines anderen Entwicklers, der Ihre Objekte verwendet. Ich habe noch nie in Teams von 100+ am selben Projekt gearbeitet, aber nach meiner Erfahrung mit Teams von 3-5 mit bis zu 20 anderen Entwicklern, die mit den von mir geschriebenen Dingen arbeiten, scheinen die anderen Bedenken dumm zu sein.

Hinweis: Ich bin hauptsächlich ein JavaScript-Entwickler. Ich mache mir im Allgemeinen keine Sorgen, dass andere Entwickler meinen Code anzeigen, und ich bin mir darüber im Klaren, dass sie meine Inhalte jederzeit einfach neu definieren können. Ich gehe davon aus, dass sie kompetent genug sind, um zu wissen, was sie zuerst tun. Wenn nicht, wäre es unwahrscheinlich, dass ich in einem Team arbeiten würde, das keine Quellcodeverwaltung verwendet.

  • Wie entscheiden Sie, ob eine bestimmte Gruppe von Eigenschaften privat sein soll oder nicht? Wenn standardmäßig jedes Feld privat sein SOLLTE, warum gibt es dann öffentliche Datenelemente in einer Klasse?

Früher hielt ich es für dumm, private Grundstücke mit Gettern und Setzern zu versehen, wenn Sie keine wirkliche Validierung oder sonstige Sonderbehandlung des einzustellenden Grundstücks durchführten. Ich denke immer noch nicht, dass es immer notwendig ist, aber wenn Sie es mit großen, hochkomplexen, aber vor allem vielen anderen Entwicklern zu tun haben, die darauf vertrauen, dass sich Ihre Objekte konsistent verhalten, kann es nützlich sein, Dinge in einer bestimmten Reihenfolge zu tun konsequente und einheitliche Weise. Wenn Leute Methoden sehen, die aufgerufen werden getThatundsetThat, sie wissen genau, was die Absichten sind, und sie können ihre Objekte schreiben, um mit Ihren zu interagieren, mit der Erwartung, dass sie immer Tomaten anstatt Tomahtos bekommen. Wenn sie dies nicht tun, wissen sie, dass Ihr Objekt ihnen etwas gibt, das es wahrscheinlich nicht sollte, was bedeutet, dass es einem anderen Objekt erlaubt, mit diesen Daten etwas zu tun, das es wahrscheinlich nicht sollte. Sie können dies bei Bedarf steuern.

Der andere große Vorteil ist, dass es einfacher ist, Ihre Objekte auf der Grundlage eines unterschiedlichen Zustandskontexts von einem Getter oder Setter abzuliefern oder Werte anders zu interpretieren. Da sie mit einer Methode auf Ihre Inhalte zugreifen, ist es viel einfacher, die Funktionsweise Ihres Objekts zu einem späteren Zeitpunkt zu ändern, ohne anderen Code zu beschädigen, der davon abhängt. Das wichtigste Prinzip ist, dass nur Ihr Objekt die Daten ändert, für die Sie es verantwortlich gemacht haben. Dies ist besonders wichtig, um Ihren Code locker zu halten. Dies ist ein großer Gewinn in Bezug auf Portabilität und einfache Modifikation.

  • Unter welchen Umständen sollte eine Variable veröffentlicht werden?

Bei erstklassigen Funktionen (Sie können Funktionen als Argumente übergeben) kann ich mir nicht viele gute Gründe vorstellen, außer dass dies bei kleineren Projekten nicht unbedingt erforderlich ist. Ohne sie, nehme ich an, haben Sie möglicherweise Mitglieder, die so stark und regelmäßig von anderen Objekten verarbeitet werden, dass es etwas unübersichtlich erscheint, ständig get und sets für ein Objekt aufzurufen, das diese Daten selbst nicht wirklich berührt, aber das in selbst würde mich fragen lassen, warum das Objekt für diese Daten verantwortlich war. Im Allgemeinen würde ich eher meine Architektur auf Fehler überprüfen wollen, bevor ich mich für eine öffentliche Dateneigenschaft entscheide. IMO, es ist nichts Falsches an einer Sprache, mit der man etwas machen kann, was normalerweise eine schlechte Idee ist. Einige Sprachen stimmen nicht überein.


Meiner Meinung nach ist es nicht besonders schlimm, eine öffentliche Klasse zu haben, deren einziger Zweck darin besteht, öffentliche Variablen offenzulegen. Tatsächlich hat die JVM eine Reihe von integrierten Klassen für diesen Zweck: int[], double[], Object[]etc. sollte man jedoch sehr vorsichtig sein , wie man Instanzen einer solchen Klasse aussetzt. Die Bedeutung von void CopyLocationTo(Point p);[ Pointvom Anrufer annehmen ] ist klarer als Point location(), da unklar ist, welche Auswirkungen Point pt = foo.location(); pt.x ++;dies auf den Standort von hat foo.
Supercat

2

Siehe diesen Beitrag von mir zu einer verwandten Frage zu SO .

Das kurze daran ist, dass Sie mit variablem Gültigkeitsbereich den Verbrauchern Ihres Codes zeigen können, mit was sie sich anlegen sollen und was nicht. Eine private Variable kann Daten enthalten, die mithilfe eines Eigenschaftssetzers oder einer Verarbeitungsmethode "überprüft" wurden, um sicherzustellen, dass sich das gesamte Objekt im konsistenten Zustand befindet. Wenn Sie den Wert der privaten Variablen direkt ändern, wird das Objekt möglicherweise inkonsistent. Wenn jemand es privat macht, muss er sehr hart arbeiten und über sehr hohe Laufzeitberechtigungen verfügen, um es zu ändern.

Das richtige Scoping der Mitglieder ist daher der Schlüssel zum selbstdokumentierenden Code.


2

Ich werde den Wert der Verkapselung aus einer anderen Perspektive anhand eines realen Beispiels erläutern. Vor einiger Zeit (Anfang der 80er Jahre) wurde ein Spiel für den Radio Shack Color Computer namens Dungeons of Daggorath geschrieben. Vor einigen Jahren portierte Richard Hunerlach es von einem Paper Assembler Listing nach C / C ++ ( http://mspencer.net/daggorath/dodpcp.html ). Einige Zeit später bekam ich den Code und begann ihn neu zu faktorisieren, um eine bessere Kapselung zu erzielen ( http://dbp-consulting.com/stuff/ ).

Der Code wurde bereits in verschiedene Objekte eingeteilt, um Zeitplanung, Video, Benutzereingaben, Dungeonerstellung, Monster usw. zu handhaben, aber Sie konnten definitiv erkennen, dass er von Assembler portiert wurde. Meine größte Aufgabe war es, die Verkapselung zu verbessern. Damit meine ich verschiedene Teile des Codes, um ihre Nasen aus dem Geschäft des anderen herauszuholen. Es gab zum Beispiel viele Stellen, an denen Videovariablen direkt geändert wurden, um eine gewisse Wirkung zu erzielen. Einige machten es mit Fehlerprüfung, andere nicht, andere hatten subtil andere Vorstellungen davon, was es bedeutete, diese Sache zu ändern. Es wurde viel Code dupliziert. Stattdessen musste der Videobereich über eine Benutzeroberfläche verfügen, um die gewünschten Aufgaben ausführen zu können, und der Code dafür konnte sich an einem Ort befinden, an einer Idee, an einem Ort, an dem das Debugging durchgeführt werden musste. So etwas war weit verbreitet.

Als der Code zu zerreißen begann, verschwanden Fehler, die noch nicht einmal diagnostiziert worden waren. Der Code wurde von höherer Qualität. Für jede Aufgabe wurde eine Stelle im Code verantwortlich, und es gab nur eine Stelle, um sie richtig zu machen. (Ich finde immer noch mehr, wenn ich den Code noch einmal durchsuche.)

Alles, was an Ihrem Code sichtbar ist, ist Ihre Schnittstelle. Ob du es so meinst oder nicht. Wenn Sie die Sichtbarkeit so weit wie möglich einschränken, werden Sie nicht versucht sein, den Code später an der falschen Stelle abzulegen. Es wird deutlich, welcher Teil des Codes für welche Daten verantwortlich ist. Es sorgt für ein besseres, saubereres, einfacheres und eleganteres Design.

Wenn Sie ein Objekt für seine eigenen Daten verantwortlich machen und Schnittstellen für alle anderen Benutzer bereitstellen, die etwas tun müssen, wird Ihr Code um ein Vielfaches einfacher. Es fällt einfach raus. Sie haben kleine einfache Routinen, die nur eines tun. Weniger Komplexität == weniger Bugs.


Die harte Balance zwischen "der Freiheit unserer Bibliotheksbenutzer" und "weniger Ärger für uns". Ich beginne zu glauben, dass die Kapselung in einem Sinne besser ist, dass ich Fehler in meiner eigenen Codierung verhindern und Endbenutzern helfen werde, Fehler zu verhindern. Aber der Mangel an Freiheit kann sie auch einfach beiseite schieben und nach Alternativen suchen ... Möglicherweise wird die Codierung noch nicht verwendet, aber vorgesehene Funktionalitäten durch öffentliche Methoden können dabei helfen, dies auszugleichen, erfordern jedoch mehr Zeit.
Aquarius Power

Schade, die überarbeitete Version ist nicht auf Github ....
Jmoreno

2

Es hat nichts mit Vertrauen oder Angst vor Angriffen zu tun, es geht ausschließlich um Kapselung - nicht um das Erzwingen unnötiger Informationen für den Benutzer der Klasse.

Betrachten Sie private Konstanten - sie sollten keine geheimen Werte enthalten (diese sollten an anderer Stelle gespeichert sein), sie können nicht geändert werden, sie müssen nicht in Ihre Klasse übergeben werden (andernfalls müssten sie öffentlich sein). Sie können nur als Konstanten in ANDEREN Klassen verwendet werden. Aber wenn Sie das tun, hängen diese Klassen jetzt von Ihrer Klasse ab, um Arbeiten auszuführen, die nichts mit Ihrer Klasse zu tun haben. Wenn Sie die Konstante ändern, können andere Klassen beschädigt werden. Das ist von beiden Seiten schlecht - als Autor Ihrer Klasse möchten Sie, dass sich die Freiheit so weit wie möglich ändert, und Sie möchten sich keine Sorgen über Dinge machen, die außerhalb Ihrer Kontrolle liegen. Ein Verbraucher Ihrer Klasse möchte sich auf die offen gelegten Details Ihrer Klasse verlassen können, ohne sich Sorgen machen zu müssen, dass Sie sie ändern und ihren Code brechen.

Ein Verbraucher Ihrer Klasse möchte alles wissen, was für die Interaktion mit Ihrer Klasse erforderlich ist, und möchte nichts über Ihre Klasse wissen, was nichts an der Art und Weise ändert, in der sie dies tun: Es sind nutzlose Kleinigkeiten. Wenn Sie eine Sprache mit Reflektion verwendet haben, wie oft haben Sie sie verwendet, um nicht zu erfahren, wie eine Klasse etwas tut oder wo sie unerwartet eine Ausnahme auslöst, sondern einfach den Namen der privaten Felder und Methoden? Ich wette nie. Weil Sie dieses Wissen nicht brauchen.


1

Das OOP-Konzept hat eine Vererbungsfunktion (Java oder C ++). Wenn wir also erben (dh auf die Variablen der geerbten Klasse zugreifen), besteht die Möglichkeit, dass diese Variablen beeinflusst werden. Wir müssen also entscheiden, ob die Variablen geändert werden können oder nicht.

Nur zu diesem Zweck verwenden wir Zugriffsmodifikatoren in OOP. Einer der Modifikatoren ist privat, was bedeutet, dass nur auf diese Klasse zugegriffen werden kann. Jede andere Klasse kann diese Variablen nicht beeinflussen.

Wie wir wissen, bedeutet geschützt, dass die Klasse, die erben wird, darauf zugreifen kann.

Warum es in OOP ein Modifikatorkonzept gibt, liegt an diesen Gründen (jede Klasse kann mithilfe des OOP-Konzepts auf andere Klassenvariablen zugreifen). Wenn es kein Modifikatorkonzept gibt, bedeutet dies, dass es schwierig gewesen wäre, Klassen zu erben oder andere OOP-Konzepte zu verwenden.


1

Wie von anderen angegeben, sind private Variablen gut, um Missbrauch zu vermeiden, der das Objekt in einen inkonsistenten Status versetzt und es schwierig macht, Fehler und unvorhergesehene Ausnahmen zu verfolgen.

Auf der anderen Seite geht es jedoch meistens um geschützte Felder, die von den anderen ignoriert wurden.

Eine erweiterte Unterklasse hat uneingeschränkten Zugriff auf geschützte Felder, wodurch das Objekt so fragil wird, als ob solche Felder öffentlich wären. Diese Fragilität ist jedoch auf die erweiterte Klasse selbst beschränkt (es sei denn, sie macht solche Felder noch stärker verfügbar).

Öffentliche Felder sind daher schwer als gut einzustufen, und bis jetzt werden sie nur für Klassen verwendet, die als Konfigurationsparameter verwendet werden (eine sehr einfache Klasse mit vielen Feldern und keiner Logik, sodass diese Klasse nur als Parameter an übergeben wird eine Methode).

Andererseits verringern private Felder die Flexibilität Ihres Codes für andere Benutzer.

Flexibilität vs. Probleme, Vor- und Nachteile:

Objekte, die von Ihrem Code in der Vanilla-Klasse mit geschützten Feldern instanziiert wurden, sind sicher und liegen in Ihrer alleinigen Verantwortung.

Objekte, die Ihre Klasse mit geschützten Feldern erweitern, die von den Benutzern Ihres Codes instanziiert werden, liegen in ihrer Verantwortung und nicht in Ihrer.

Wenn also geschützte Felder / Methoden nicht gut dokumentiert sind oder die Benutzer nicht wirklich verstehen, wie solche Felder und Methoden verwendet werden sollten, haben sie eine gute Chance, sich und Ihnen unnötige Probleme zu bereiten.

Wenn Sie jedoch die meisten Dinge privat machen, wird die Flexibilität der Benutzer eingeschränkt, und sie werden möglicherweise sogar auf der Suche nach Alternativen sein, da sie möglicherweise keine Abzweigung erstellen und warten möchten, damit die Dinge auf ihre Weise geschehen.

Entscheidend ist also ein ausgewogenes Verhältnis zwischen privat, geschützt und öffentlich.

Jetzt ist die Entscheidung zwischen privat und geschützt das eigentliche Problem.

Wann geschützte verwenden?

Jedes Mal, wenn Sie verstehen, dass ein Feld sehr flexibel sein kann, sollte es als geschützt codiert werden. Diese Flexibilität ist: von Null werden (wobei Null immer geprüft und als gültiger Zustand erkannt wird, der keine Ausnahmen auslöst) bis zu Einschränkungen, bevor sie von Ihrer Klasse ex verwendet werden. > = 0, <100 usw. und automatisch für über- / untergelaufene Werte festgelegt, wobei höchstens eine Warnmeldung ausgegeben wird.

Für ein solches geschütztes Feld könnten Sie also einen Getter erstellen und nur diesen verwenden (anstatt die Feldvariable direkt zu verwenden), während andere Benutzer ihn möglicherweise nicht verwenden, falls sie mehr Flexibilität für ihren spezifischen Code wünschen, wie in meinem Beispiel : wenn sie wollen, dass negative Werte in ihrer erweiterten Klasse gut funktionieren.


-1

imo @tdammers hat nicht recht und ist eigentlich irreführend.

Private Variablen dienen zum Ausblenden von Implementierungsdetails. Ihre Klasse verwendet Amöglicherweise ein array, um Punkte zu speichern. Morgen möchten Sie vielleicht ein treeoder priority queueverwenden. Alle Benutzer Ihrer Klasse benötigen eine Möglichkeit, Punkte und Namen einzugeben und addScore()herauszufinden, wer die Top 10 sind getTop(n).

Sie müssen nicht auf die zugrunde liegende Datenstruktur zugreifen. Klingt gut? Nun, es gibt einige Einschränkungen.

Sie sollten sowieso nicht viel Staat speichern, das meiste davon wird nicht benötigt. Durch das Speichern des Status wird der Code selbst dann kompliziert, wenn er in eine bestimmte Klasse unterteilt ist. Denken Sie darüber nach, diese private Variable hat sich wahrscheinlich geändert, weil ein anderes Objekt eine Methode dieser Klasse genannt hat. Sie müssen noch herausfinden, wann und wo diese Methode aufgerufen wurde, und diese öffentliche Methode kann theoretisch überall aufgerufen werden.

Das Beste, was Sie tun können, ist, den in Ihrem Programm enthaltenen Status zu begrenzen und möglichst reine Funktionen zu verwenden.


-1
  • Zugriff auf eine Variable bedeutet Zugriff auf ihren Wert, wenn das Programm ausgeführt wird. Wenn Sie eine Variable als privat kennzeichnen, wird ihr Wert geschützt , wenn der Code ausgeführt wird.
  • Der Punkt des sogenannten "Versteckens von Daten" besteht darin, interne Daten vor anderen Klassen, die die Klasse verwenden, verborgen zu halten. Diese anderen Klassen sollten auf das Verhalten nur zugreifen, indem sie Methoden für die Klasse aufrufen, nicht indem sie Werte von Variablen direkt ändern.
  • Indem Sie die Variable zu einem privaten Datenelement machen, können Sie einfacher sicherstellen, dass der Wert niemals geändert oder geändert wird. Wenn die Variable dagegen öffentlich ist, kann eine andere Klasse den Wert ändern oder ändern, wodurch andere Teile des Codes abstürzen können.

1
dies scheint nicht alles zu bieten erhebliche über Punkte gemacht und erläutert vor 17 Antworten
gnat

-4

Sie sollten zunächst das Konzept der objektorientierten Programmierung verstehen. Es hat Abstraktion, Einkapselung usw.

Abstraktion - Sie erhalten eine Vorstellung von der Logik, ohne die Details der Implementierung hervorheben zu müssen.

Kapselung - Sie können die unterstrichene Implementierung des Objekts nicht sehen. Nur Sie können die öffentliche Oberfläche des Objekts sehen.

Jetzt können Sie in einer spezifischen Implementierung mit einem objektorientierten Programm wie C #, Java, C ++ diese Konzepte implementieren.

privat - Die Implementierung, die vor der Außenwelt verborgen bleiben soll. Damit Sie das ändern können und der Benutzer Ihrer Klasse davon nicht betroffen ist.

public - Dies ist die Schnittstelle, über die Sie Ihr Objekt verwenden können.


1
protected - direkt zugänglich für Unterklassen (Extender) (Java).
Aquarius Power
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.