Ist die Sichtbarkeit private
von Klassenfeldern / Eigenschaften / Attributen sinnvoll? In OOP werden Sie früher oder später eine Unterklasse einer Klasse erstellen. In diesem Fall ist es gut, die Implementierung zu verstehen und sie vollständig ändern zu können.
Eines der ersten Dinge, die ich mache, wenn ich eine Klasse untergeordnete, ist die Änderung einer Reihe von private
Methoden in protected
. Es ist jedoch wichtig , Details vor der Außenwelt zu verbergen - also brauchen wir protected
und nicht nur public
.
Meine Frage ist: Kennen Sie einen wichtigen Anwendungsfall, bei dem es sich private
nicht protected
um ein gutes Tool handelt, oder würden zwei Optionen " protected
& public
" für OOP-Sprachen ausreichen?
object-oriented
encapsulation
access-modifiers
Adam Libuša
quelle
quelle
Antworten:
Denn wie Sie sagen,
protected
bleibt Ihnen immer noch die Möglichkeit, "die Implementierung komplett zu modifizieren". Es schützt nichts in der Klasse.Warum ist es uns wichtig, das Zeug in der Klasse "wirklich zu schützen"? Andernfalls ist es unmöglich, Implementierungsdetails zu ändern, ohne den Clientcode zu beschädigen . Anders ausgedrückt, Leute, die Unterklassen schreiben, sind auch "die Außenwelt" für die Person, die die ursprüngliche Basisklasse geschrieben hat.
In der Praxis sind
protected
Mitglieder im Wesentlichen eine "öffentliche API für Unterklassen" der Klasse und müssen ebenso stabil und abwärtskompatibel bleiben wiepublic
Mitglieder. Wenn wir nicht die Möglichkeit haben , um wahr zu schaffenprivate
Mitglieder, dann nichts in einer Implementierung würde jemals sicher zu sein , zu ändern, weil Sie nicht die Möglichkeit auszuschließen, wäre in der Lage , dass (nicht-bösartige) Client - Code irgendwie an hat es geschafft , hängen es.Übrigens: Während in OOP früher oder später eine Unterklasse einer Klasse erstellt wird, scheint Ihr Argument die viel stärkere Annahme zu treffen, dass Sie früher oder später eine Unterklasse erstellen werden jede Klasse ", was mit ziemlicher Sicherheit nicht der Fall ist.
quelle
private
, dass es für mich wirklich Sinn macht. Die lib-Perspektive muss öfter verwendet werden, sonst könnte jeder, der die (C-artige) Codierungsmentalität "absolute Kontrolle, absolute Verantwortung" mag, sie als "Schützt mich vor mir selbst" kennzeichnen. Beachten Sie, dass ich früherprivate
immer noch verwendet habe . Ich fühlte mich einfach immer gut dokumentiert, und eine Namenskonvention_foo
, die darauf hinweist, dass Sie wahrscheinlich nicht damit herumspielen sollten, war gleichbedeutend, wenn nicht sogar besser. Deterministisch sagen zu können, dass "nichts kaputt gehen wird", ist ein legitimes undprivate
einziges Merkmal.Das ist falsch. Nicht jede Klasse ist als Unterklasse gedacht, und einige statisch typisierte OOP-Sprachen verfügen sogar über Funktionen, die dies verhindern, z. B.
final
(Java und C ++) odersealed
(C #).Nein, ist es nicht. Es ist gut für eine Klasse, ihre öffentliche Schnittstelle klar zu definieren und ihre Invarianten beizubehalten, selbst wenn sie von geerbt wird.
Bei der Zugangskontrolle geht es im Allgemeinen um die Unterteilung. Sie möchten, dass ein einzelner Teil des Codes verstanden wird, ohne im Detail zu verstehen, wie er mit dem Rest des Codes interagiert. Privater Zugang erlaubt das. Wenn alles mindestens geschützt ist, müssen Sie verstehen, was jede Unterklasse tut, um zu verstehen, wie die Basisklasse funktioniert.
Oder um es in den Begriffen von Scott Meyers auszudrücken: Private Teile einer Klasse sind von einer endlichen Menge an Code betroffen: dem Code der Klasse selbst.
Öffentliche Teile sind potenziell von jedem vorhandenen Codebit und jedem noch zu schreibenden Codebit betroffen, was eine unendliche Menge an Code darstellt.
Geschützte Teile sind möglicherweise von jeder vorhandenen Unterklasse und jeder noch zu schreibenden Unterklasse betroffen, was ebenfalls eine unendliche Menge an Code darstellt.
Die Schlussfolgerung ist, dass Sie mit protected nur wenig mehr als mit public erhalten, während private Ihnen eine echte Verbesserung bringen. Die Existenz des geschützten Zugriffsspezifizierers ist fraglich, nicht privat.
quelle
virtual
aus den in dieser Antwort genannten Gründen ausdrücklich als gekennzeichnet .protected
ist für Methoden, nicht für Datenmitglieder.sealed
große Teile der .net-Bibliothek und des IIRC, warum er den Rest gerne eingesperrt hätte. In dem Moment, in dem Sie zulassen, dass Vererbungen von Drittanbietern interne Werte berühren, müssen Sie jeder Methode eine große Menge an Validierungs- / Sicherheitsüberprüfungen hinzufügen, da Sie keinen Konstruktionsinvarianten mehr in Bezug auf den internen Status des Objekts vertrauen können.Ja, private Felder sind unbedingt erforderlich. Gerade diese Woche musste ich eine Implementierung eines benutzerdefinierten Wörterbuchs schreiben, in der ich kontrollierte, was in das Wörterbuch eingefügt wurde. Wenn das Wörterbuchfeld geschützt oder öffentlich gemacht werden soll, können die von mir so sorgfältig geschriebenen Steuerelemente leicht umgangen werden.
Bei privaten Feldern geht es in der Regel darum, sicherzustellen, dass die Daten dem erwarteten ursprünglichen Codierer entsprechen. Machen Sie alles geschützt / öffentlich und fahren Sie mit einer Kutsche und Pferden durch diese Verfahren und Validierung.
quelle
private
ist nur eine Art zu sagen, "fassen Sie diese nicht an" und lassen Sie es im Compilervertrag durchsetzen. In Systemen wie .NET hat dies auch wichtige Auswirkungen auf die Sicherheit. Sie können die Privatsphäre anderer nur dann berühren, wenn Sie volles Vertrauen haben (im Grunde das Äquivalent zu Administrator- / Root-Zugriff).Bei dem Versuch, formal über die Richtigkeit eines objektorientierten Programms nachzudenken, ist es typisch , einen modularen Ansatz zu verwenden, der Objektinvarianten einbezieht . bei diesem Ansatz
Das modulare Denken über ein Objekt läuft wie folgt ab (zumindest in erster Näherung)
Stellen Sie sich vor, wir überprüfen eine
object A
Verwendung des obigen Ansatzes. Und nun will , um zu überprüfenmethod g
vonobject B
den Anrufenmethod f
vonobject A
. Dank des modularen Denkens können wir überlegen,method g
ohne die Implementierung von überdenken zu müssenmethod f
. Vorausgesetzt, wir können die Invariante vonobject A
und die Vorbedingung vonmethod f
am Aufrufort festlegen, indemmethod g,
wir die Post-Bedingung vonmethod f
als eine Zusammenfassung des Verhaltens des Methodenaufrufs betrachten. Darüber hinaus wissen wir auch, dass nach der Rückgabe des Anrufs die Invariante vonA
still gilt.Diese Modularität des Denkens ermöglicht es uns, formal über große Programme nachzudenken. Wir können über jede der Methoden einzeln argumentieren und dann die Ergebnisse dieser Argumentation zusammenfassen, um über größere Teile des Programms zu argumentieren.
Private Felder sind in diesem Prozess sehr nützlich. Um zu wissen, dass die Invariante eines Objekts zwischen zwei Methodenaufrufen für dieses Objekt bestehen bleibt, verlassen wir uns normalerweise darauf, dass das Objekt in der Zwischenzeit nicht geändert wird.
Damit das modulare Denken in einem Kontext funktioniert, in dem Objekte keine privaten Felder haben, muss sichergestellt werden, dass die Invariante immer (nach dem Feld) wiederhergestellt wird, auf was auch immer ein Feld von einem anderen Objekt gesetzt wurde einstellen). Es ist schwierig, sich eine Objektinvariante vorzustellen, die unabhängig vom Wert der Felder des Objekts beides enthält und die auch nützlich ist, um über die Korrektheit des Programms nachzudenken. Wir müssten wahrscheinlich eine komplizierte Konvention für den Feldzugang erfinden. Und wahrscheinlich verlieren auch einige (im schlimmsten Fall sogar alle) unserer Fähigkeit, modular zu argumentieren.
Geschützte Felder
Geschützte Felder stellen einen Teil unserer Fähigkeit wieder her, modular zu argumentieren. Je nach Sprache
protected
kann die Möglichkeit eingeschränkt sein, ein Feld auf alle Unterklassen oder alle Unterklassen und Klassen desselben Pakets festzulegen. Es kommt häufig vor, dass wir nicht auf alle Unterklassen zugreifen können, wenn wir über die Richtigkeit eines von uns geschriebenen Objekts nachdenken. Beispielsweise schreiben Sie möglicherweise eine Komponente oder Bibliothek, die später in einem größeren Programm (oder mehreren größeren Programmen) verwendet wird - von denen einige möglicherweise noch nicht einmal geschrieben wurden. In der Regel wissen Sie nicht, ob und in welcher Weise eine Unterklasse vorliegt.Normalerweise ist es jedoch Aufgabe einer Unterklasse, die Objektinvariante der Klasse, die sie erweitert, beizubehalten. In einer Sprache, in der schützen nur "Unterklasse" bedeutet und in der wir diszipliniert dafür sorgen, dass Unterklassen immer die Invarianten ihrer Oberklasse beibehalten, kann man argumentieren, dass die Wahl der Verwendung von geschützt anstelle von privat nur minimale Modularität verliert .
Obwohl ich über formale Argumente gesprochen habe, wird oft angenommen, dass Programmierer, die informelle Gründe für die Richtigkeit ihres Codes haben, manchmal auch auf ähnliche Argumente zurückgreifen.
quelle
private
Variablen in einer Klasse sind besser alsprotected
aus demselben Grund, aus dem einebreak
Anweisung in einemswitch
Block besser ist als einegoto label
Anweisung. Das ist, dass menschliche Programmierer fehleranfällig sind.protected
Variablen eignen sich für unbeabsichtigten Missbrauch (Programmiererfehler), genauso wie sich diegoto
Anweisung für die Erstellung von Spaghetti-Code eignet.Ist es möglich, fehlerfreien Code mit
protected
Klassenvariablen zu schreiben ? Ja natürlich! So wie es möglich ist, fehlerfreien Code mit zu schreibengoto
; aber wie es im Klischee heißt: "Nur weil du kannst, heißt das nicht, dass du sollst!"Es gibt Klassen und in der Tat das OO-Paradigma, um zu verhindern, dass unglückliche, fehleranfällige menschliche Programmierer Fehler machen. Die Abwehr menschlicher Fehler ist nur so gut wie die in die Klasse eingebauten Abwehrmaßnahmen. Die Umsetzung Ihrer Klasse
protected
ist das Äquivalent dazu, ein riesiges Loch in die Wände einer Festung zu sprengen.Basisklassen haben absolut keine Kenntnis über abgeleitete Klassen. Wenn es sich um eine Basisklasse handelt,
protected
bietet diese Klasse eigentlich keinen größeren Schutz alspublic
, da nichts eine abgeleitete Klasse davon abhält, einenpublic
Getter / Setter zu erstellen, der sich wie eine Hintertür verhält.Wenn eine Basisklasse einen ungehinderten Zugriff auf ihre internen Implementierungsdetails zulässt, ist es für die Klasse selbst unmöglich, sich gegen Fehler zu verteidigen. Basisklassen kennen ihre abgeleiteten Klassen überhaupt nicht und können sich daher nicht vor Fehlern schützen, die in diesen abgeleiteten Klassen gemacht wurden.
Das Beste, was eine Basisklasse tun kann, ist, so viel wie möglich von ihrer Implementierung zu verbergen
private
und genügend Einschränkungen zu treffen, um Änderungen von abgeleiteten Klassen oder anderen Objekten außerhalb der Klasse zu verhindern.Letztendlich existieren Hochsprachen, um menschliche Fehler zu minimieren. Es gibt auch gute Programmierpraktiken (wie SOLID-Prinzipien ), um menschliche Fehler zu minimieren.
Softwareentwickler, die gute Programmierpraktiken ignorieren, haben ein viel höheres Fehlerrisiko und führen mit größerer Wahrscheinlichkeit zu fehlerhaften, nicht zu wartenden Lösungen. Diejenigen, die sich an bewährte Verfahren halten, haben eine viel geringere Wahrscheinlichkeit, dass sie versagen, und führen mit größerer Wahrscheinlichkeit zu funktionsfähigen, wartbaren Lösungen.
quelle
public
Implementierungsdetails , weil es mir verleiht wartbaren Code. Ein kompetenter Programmierer würde es vermeiden,goto
weil es sich für nicht wartbaren Code eignet. Die reale Welt ist jedoch so, dass Sie manchmal in einem schrecklichen Durcheinander von Legacy-Code verirrt sind und keine andere Wahl haben, als diese zu verwendengoto
, und aus dem gleichen Grund haben Sie manchmal keine andere Wahl, als öffentliche / geschützte Implementierungsdetails zu verwenden.public
Eigenschaften / Schnittstelle hat, aber nicht mit Code, der nur verwendetgoto
.goto
oder liegt es nur daran, dass du solche Artikel gelesen hast? Ich verstehe, warumgoto
es böse ist, weil ich 2 Jahre lang an altem Code gearbeitet habe, der ihn verwendet. und ich habe noch länger mit Code gearbeitet, bei dem die Implementierungsdetails von "Klassen" überall durchgesickert sindpublic
undfriend
Spezifizierer als schnelle / einfache / schmutzige Hacks verwendet werden. Ich akzeptiere das Argument nicht, dass das "öffentliche Offenlegen von Implementierungsdetails" kein ineinandergreifendes Spaghetti-Chaos mit dem gleichen Schweregrad verursachen kann, wiegoto
es absolut möglich ist.Vererbbare Klassen haben zwei Verträge - einen mit Inhabern von Objektreferenzen und einen mit abgeleiteten Klassen. Öffentliche Mitglieder sind an den Vertrag mit Referenzinhabern gebunden, und geschützte Mitglieder sind an den Vertrag mit abgeleiteten Klassen gebunden.
Durch das Erstellen von Mitgliedern wird
protected
die Basisklasse vielseitiger, aber die Art und Weise, in der sich zukünftige Versionen der Klasse ändern, wird häufig eingeschränkt. Durch das Erstellen von Mitgliedernprivate
kann der Klassenautor die innere Funktionsweise der Klasse vielseitiger ändern, begrenzt jedoch die Arten von Klassen, die sinnvoll daraus abgeleitet werden können.Beispiel:
List<T>
In .NET wird der Sicherungsspeicher als privat definiert. Wenn es geschützt wäre, könnten abgeleitete Typen einige nützliche Dinge tun, die ansonsten nicht möglichList<T>
wären , aber zukünftige Versionen von müssten seinen klobigen monolithischen Hintergrundspeicher sogar für Listen mit Millionen von Elementen verwenden. Wenn Sie den Sicherungsspeicher privat machen, können zukünftige Versionen vonList<T>
einen effizienteren Sicherungsspeicher verwenden, ohne abgeleitete Klassen zu unterbrechen.quelle
Ich glaube, Ihre Argumentation geht von der Annahme aus, dass jemand, der eine Klasse schreibt, nicht weiß, wer diese Klasse später und aus welchem Grund erweitern könnte . Unter dieser Annahme ist Ihr Argument durchaus sinnvoll, da jede Variable, die Sie privat machen, möglicherweise eine Entwicklungsstraße in der Zukunft abschneidet. Diese Annahme würde ich jedoch ablehnen.
Wenn diese Annahme zurückgewiesen wird, sind nur zwei Fälle zu berücksichtigen.
In diesem Fall weiß der Autor, dass jemand die Klasse erweitern wird und warum und daher genau weiß, was geschützt und was privat gemacht werden soll. Sie verwenden die private / protected-Unterscheidung, um dem Benutzer, der die Unterklasse erstellt, eine Art Schnittstelle mitzuteilen.
Dieser Fall sollte selten vorkommen (Sie könnten argumentieren, dass er nicht legitim ist) und es wird nicht bevorzugt, nur die ursprüngliche Klasse in der ursprünglichen Codebasis zu ändern. Es könnte auch ein Symptom für schlechtes Design sein. In diesen Fällen würde ich es vorziehen, wenn die Person, die das Verhalten hackt, andere Hacks wie Friends (C / C ++) und
setAccessible(true)
(Java) verwendet.Ich denke, es ist sicher, diese Annahme abzulehnen.
Dies geht im Allgemeinen auf die Idee der Komposition über die Vererbung zurück . Vererbung wird häufig als ideale Methode zur Reduzierung der Wiederverwendung von Code gelehrt, sollte jedoch selten die erste Wahl für die Wiederverwendung von Code sein. Ich habe kein einfaches KO-Argument und es kann ziemlich schwierig und umstritten sein, es zu verstehen. Aufgrund meiner Erfahrungen mit der Domänenmodellierung habe ich jedoch festgestellt, dass ich Vererbung selten verwende, ohne genau zu wissen, wer meine Klasse aus welchem Grund erbt.
quelle
Alle drei Zugriffsebenen haben ihren Anwendungsfall, OOP wäre unvollständig, wenn keine von ihnen vorhanden wäre. Normalerweise tust du das
Und Sie weichen nur dann von diesem allgemeinen Schema ab, wenn es einen guten Grund gibt . Hüten Sie sich vor „das wird mein Leben leichter machen , wenn ich es frei von außen zugreifen kann“ (und außerhalb hier auch enthält Subklassen). Wenn ich Klassenhierarchien implementiere, beginne ich oft mit Klassen, die keine geschützten Mitglieder haben, bis ich zu deren Unterklassen / Erweiterung / Spezialisierung komme, zu den Basisklassen eines Frameworks / Toolkits werde und manchmal einen Teil ihrer ursprünglichen Funktionalität eine Ebene nach oben verschiebe.
quelle
Eine vielleicht interessantere Frage ist, warum eine andere Art von Feld als privat notwendig ist. Wenn eine Unterklasse mit den Daten einer Superklasse interagieren muss, wird direkt eine direkte Kopplung zwischen den beiden erstellt, während die Verwendung von Methoden zum Bereitstellen der Interaktion zwischen den beiden eine Indirektionsebene ermöglicht, die es ermöglicht, Änderungen an den Daten einer Superklasse vorzunehmen Superklasse, die sonst sehr schwierig wäre.
Einige Sprachen (z. B. Ruby und Smalltalk) stellen keine öffentlichen Felder zur Verfügung, sodass Entwickler davon abgehalten werden, eine direkte Kopplung mit ihren Klassenimplementierungen zuzulassen. Warum aber nicht weiter gehen und nur private Felder verwenden? Es würde keinen Verlust an Allgemeinheit geben (da die Oberklasse immer geschützte Zugriffsmechanismen für die Unterklasse bereitstellen kann), aber dies würde sicherstellen, dass Klassen immer mindestens einen geringen Grad an Isolation von ihren Unterklassen aufweisen. Warum ist dies kein häufigeres Design?
quelle
Viele gute Antworten hier, aber ich werfe trotzdem meine zwei Cent ein. :-)
Privat ist aus demselben Grund gut, aus dem auch globale Daten schlecht sind.
Wenn eine Klasse Daten als privat deklariert, wissen Sie absolut, dass der einzige Code, der mit diesen Daten in Konflikt gerät, der Code in der Klasse ist. Wenn ein Fehler auftritt, müssen Sie nicht die gesamte Erstellung durchsuchen, um alle Stellen zu finden, an denen diese Daten möglicherweise geändert werden. Sie wissen, dass es in der Klasse ist. Wenn Sie eine Änderung am Code vornehmen und Änderungen an der Verwendung dieses Felds vornehmen, müssen Sie nicht alle potenziellen Stellen ausfindig machen, an denen dieses Feld verwendet werden könnte, und untersuchen, ob Ihre geplante Änderung sie beschädigen wird. Sie wissen, dass die einzigen Orte in der Klasse sind.
Ich musste viele, viele Male Änderungen an Klassen vornehmen, die sich in einer Bibliothek befinden und von mehreren Apps verwendet werden, und ich muss sehr vorsichtig vorgehen, um sicherzustellen, dass ich keine App beschädige, über die ich nichts weiß. Je mehr öffentliche und geschützte Daten vorhanden sind, desto größer ist die Gefahr von Problemen.
quelle
Ich denke, es lohnt sich, einige abweichende Meinungen zu erwähnen.
Theoretisch ist es aus allen in den anderen Antworten genannten Gründen gut, die Zugriffsebene kontrolliert zu haben.
In der Praxis sehe ich bei der Codeüberprüfung zu oft Leute (die gerne privat arbeiten), die die Zugriffsebene von privat -> geschützt und nicht zu oft von geschützt -> öffentlich ändern. Das Ändern von Klasseneigenschaften erfordert fast immer das Ändern von Setter / Gettern. Diese haben viel meiner Zeit (Codeüberprüfung) und ihrer Zeit (Codeänderung) verschwendet.
Es ärgert mich auch, dass dies bedeutet, dass ihre Klassen nicht für Änderungen geschlossen sind.
Das war mit internem Code, wo Sie es immer ändern können, wenn Sie auch brauchen. Bei Code von Drittanbietern ist die Situation noch schlimmer, wenn es nicht so einfach ist, den Code zu ändern.
Wie viele Programmierer halten das für einen Ärger? Nun, wie viele verwenden Programmiersprachen, die keine privaten haben? Natürlich verwenden die Leute nicht nur diese Sprachen, weil sie keine privaten Spezifizierer haben, aber es hilft, die Sprachen zu vereinfachen, und Einfachheit ist wichtig.
Imo ist es sehr ähnlich zu dynamischer / statischer Eingabe. Theoretisch ist die statische Typisierung sehr gut. In der Praxis verhindert es nur wie 2% der Fehler die Unvernünftige Wirksamkeit der dynamischen Typisierung ... . Die Verwendung von privat verhindert wahrscheinlich weniger Fehler.
Ich denke, dass SOLID-Prinzipien gut sind, und ich wünsche mir, dass sich die Leute mehr für sie interessieren als für die Schaffung einer Klasse mit öffentlichen, geschützten und privaten.
quelle
Ich möchte auch ein weiteres praktisches Beispiel hinzufügen, warum dies
protected
nicht ausreicht. An meiner Universität unternehmen die ersten Jahre ein Projekt, bei dem sie eine Desktop-Version eines Brettspiels entwickeln müssen (für das später eine KI entwickelt und über ein Netzwerk mit anderen Spielern verbunden wird). Ihnen wird ein Teilcode zur Verfügung gestellt, um sie mit einem Testframework zum Einstieg zu bewegen. Einige der Eigenschaften der Hauptspielklasse werden offengelegt,protected
damit die Testklassen, die diese Klasse erweitern, auf sie zugreifen können. Diese Felder sind jedoch keine vertraulichen Informationen.Als TA für die Einheit sehe ich oft Studenten einfach machen alle zusätzlichen Code
protected
oderpublic
(vielleicht , weil sie die anderen sahprotected
undpublic
Sachen und nahm sie sollten folgen). Ich frage sie, warum ihr Schutzniveau unangemessen ist und viele wissen nicht warum. Die Antwort ist, dass die sensiblen Informationen, die sie Subklassen aussetzen, bedeuten, dass ein anderer Spieler schummeln kann, indem er einfach diese Klasse erweitert und auf die hochsensiblen Informationen für das Spiel zugreift (im Wesentlichen die verborgene Position des Gegners, denke ich ähnlich wie bei Ihnen könnte die Teile deines Gegners auf einem Schlachtschiffbrett sehen, indem du eine Klasse ausbaust). Das macht ihren Code im Kontext des Spiels sehr gefährlich.Abgesehen davon gibt es viele andere Gründe, etwas für Ihre Unterklassen geheim zu halten. Es kann sein, dass Implementierungsdetails ausgeblendet werden, die die korrekte Arbeitsweise der Klasse beeinträchtigen, wenn sie von jemandem geändert werden, der nicht unbedingt weiß, was er tut (meistens denken sie daran, dass andere Ihren Code hier verwenden).
quelle
Private Methoden / Variablen werden in der Regel vor einer Unterklasse verborgen. Das kann gut sein.
Eine private Methode kann Annahmen über Parameter treffen und die Überprüfung der Integrität dem Aufrufer überlassen.
Eine geschützte Methode sollte Eingaben auf ihre Richtigkeit überprüfen.
quelle
"privat" bedeutet: Nicht für andere Personen als die Klasse selbst bestimmt. Nicht dazu gedacht, von Unterklassen geändert oder aufgerufen zu werden. Unterklassen? Welche Unterklassen? Du sollst das nicht unterordnen!
"protected" bedeutet: Nur zum Ändern von oder Zugreifen auf Klassen oder Unterklassen vorgesehen. Wahrscheinlich Abzug, den du unterordnen sollst, sonst warum "geschützt" und nicht "privat"?
Hier gibt es einen deutlichen Unterschied. Wenn ich etwas privat mache, solltest du deine schmutzigen Finger davon lassen. Auch wenn Sie eine Unterklasse sind.
quelle
Einige Überlegungen zu
private
vs.protected
Methoden :private
Methoden verhindern die Wiederverwendung von Code. Eine Unterklasse kann den Code nicht in der privaten Methode verwenden und muss ihn möglicherweise erneut implementieren - oder die ursprünglich von der privaten Methode & c abhängigen Methoden erneut implementieren.Andererseits kann jede Methode, die nicht
private
als API angesehen werden kann, die von der Klasse für "die Außenwelt" bereitgestellt wird, in dem Sinne, dass Unterklassen von Drittanbietern auch als "Außenwelt" betrachtet werden, wie jemand anderes in seiner Antwort vorgeschlagen hat bereits.Ist das etwas schlechtes? - Das glaube ich nicht.
Natürlich sperrt eine (pseudo-) öffentliche API den ursprünglichen Programmierer und behindert das Refactoring dieser Schnittstellen. Aber umgekehrt: Warum sollte ein Programmierer seine eigenen "Implementierungsdetails" nicht so sauber und stabil gestalten wie seine öffentliche API? Sollte er
private
damit umgehen, um seinen "privaten" Code zu strukturieren? Denken Sie vielleicht, dass er es später aufräumen könnte, weil niemand es bemerken wird? - Nein.Der Programmierer sollte auch ein wenig über seinen "privaten" Code nachdenken, um ihn so zu strukturieren, dass er die Wiederverwendung von so viel wie möglich überhaupt erst ermöglicht oder sogar fördert. Dann werden die nicht-privaten Teile in Zukunft möglicherweise nicht mehr so belastend wie manche befürchten.
Eine Menge (Framework-) Code, den ich sehe, verwendet uneinheitlich
private
:protected
Nicht endgültige Methoden, die kaum mehr als das Delegieren an eine private Methode leisten, sind häufig anzutreffen.protected
, nicht endgültige Methoden, deren Vertrag nur durch direkten Zugang zu privaten Feldern erfüllt werden kann.Diese Methoden können logisch nicht überschrieben / erweitert werden, obwohl technisch nichts da ist, was das (Compiler-) offensichtlich macht.
Wünschen Sie Erweiterbarkeit und Vererbung? Machen Sie nicht Ihre Methoden
private
.Willst du nicht, dass sich ein bestimmtes Verhalten deiner Klasse ändert? Machen Sie Ihre Methoden
final
.Können Sie Ihre Methode wirklich nicht außerhalb eines bestimmten, genau definierten Kontexts aufrufen lassen? Stellen Sie Ihre Methode bereit
private
und / oder überlegen Sie, wie Sie den erforderlichen gut definierten Kontext für die Wiederverwendung durch eine andereprotected
Wrapper-Methode verfügbar machen können .Deshalb empfehle ich,
private
sparsam zu verwenden . Und nicht zu verwechselnprivate
mitfinal
. - Wenn die Implementierung einer Methode für den allgemeinen Vertrag der Klasse von entscheidender Bedeutung ist und daher nicht ersetzt / überschrieben werden darf, machen Sie esfinal
!Für Felder
private
ist das nicht wirklich schlecht. Solange das / die Feld (er) mit geeigneten Methoden sinnvoll "genutzt" werden kann (das ist nichtgetXX()
odersetXX()
!).quelle
private
vsprotected
ursprüngliche Frage, gibt irrt Rat ( „verwendenprivate
? Sparsam“) und geht gegen den allgemeinen Konsens über OO - Design. Verwendenprivate
hat nichts damit zu tun, schlampigen Code zu verbergen.private
dazu bei, die API sauber zu halten.Privat : Wenn Sie etwas haben, das für eine Unterklasse zum Aufrufen oder Überschreiben niemals nützlich sein wird.
Geschützt : wenn Sie etwas haben, das eine Unterklassen-spezifische Implementierung / Konstante hat.
Ein Beispiel:
quelle
Es war schwer für mich, diese Angelegenheit zu verstehen, deshalb möchte ich einen Teil meiner Erfahrung teilen:
$classInstance->field
. Und der Trick, dass es "das ist es" ist. Die Kinder Ihrer Klasse haben uneingeschränkten Zugriff darauf, da dies ihr rechtmäßiger interner Teil ist.UPDATE: Ein praktisches Beispiel für eine echte Aufgabe, die ich gelöst habe. Hier ist es: Sie haben ein Token wie USB oder LPT (das war mein Fall) und Sie haben eine Middleware. Der Token fragt Sie nach einem PIN-Code, öffnet sich, wenn er korrekt ist, und Sie können einen verschlüsselten Teil und eine Reihe von Schlüsseln zum Entschlüsseln senden. Die Schlüssel werden im Token gespeichert, Sie können sie nicht lesen, sondern nur verwenden. Und es gab temporäre Schlüssel für eine Sitzung, die von einem Schlüssel in einem Token signiert, aber in einer Middleware selbst gespeichert wurden. Der temporäre Schlüssel sollte nicht irgendwo draußen lecken, sondern nur auf Fahrerebene existieren. Und ich habe private Felder verwendet, um diesen temporären Schlüssel und einige Hardware-Verbindungsdaten zu speichern. Daher konnten keine Derivate nicht nur eine öffentliche Schnittstelle verwenden, sondern auch einige geschützte"handliche" Unterprogramme, die ich für eine Aufgabe erstellt habe, aber mit den Tasten und der HW-Interaktion nicht in der Lage waren, einen Geldschrank zu öffnen. Macht Sinn?
quelle