Frage

Sollten Sie jemals geschützte Mitgliedsvariablen verwenden?Was sind die Vorteile und welche Probleme kann dies verursachen?

War es hilfreich?

Lösung

Sollten Sie jemals geschützte Mitgliedsvariablen verwenden?

Hängt davon ab, wie wählerisch Sie beim Verstecken des Status sind.

  • Wenn Sie nicht möchten, dass der interne Status verloren geht, ist es die richtige Lösung, alle Ihre Mitgliedsvariablen als privat zu deklarieren.
  • Wenn es Ihnen egal ist, dass Unterklassen auf den internen Status zugreifen können, ist protected ausreichend.

Wenn ein Entwickler vorbeikommt und Ihre Klasse in Unterklassen unterteilt, kann es sein, dass er es vermasselt, weil er es nicht vollständig versteht.Bei privaten Mitgliedern können sie, abgesehen von der öffentlichen Schnittstelle, die Implementierungsdetails der Vorgehensweise nicht sehen, was Ihnen die Flexibilität gibt, sie später zu ändern.

Andere Tipps

Heutzutage herrscht allgemein der Eindruck, dass sie eine unangemessene Kopplung zwischen abgeleiteten Klassen und ihren Basen verursachen.

Sie haben keinen besonderen Vorteil gegenüber geschützten Methoden/Eigenschaften (früher hatten sie möglicherweise einen leichten Leistungsvorteil), und sie wurden auch häufiger in einer Zeit verwendet, in der eine sehr tiefe Vererbung in Mode war, was derzeit nicht der Fall ist.

Wenn etwas nicht bewusst als öffentlich gedacht ist, mache ich es im Allgemeinen privat.

Wenn eine Situation auftritt, in der ich Zugriff auf diese private Variable oder Methode einer abgeleiteten Klasse benötige, ändere ich sie von „privat“ in „geschützt“.

Das kommt so gut wie nie vor – ich bin eigentlich überhaupt kein Fan von Vererbung, da sich damit die meisten Situationen nicht besonders gut modellieren lassen.Auf jeden Fall weitermachen, keine Sorge.

Ich würde sagen, dass dies für die Mehrheit der Entwickler in Ordnung ist (und wahrscheinlich der beste Weg ist).

Die einfache Tatsache ist, Wenn ein Jahr später ein anderer Entwickler auftaucht und entscheidet, dass er Zugriff auf Ihre private Mitgliedsvariable benötigt, wird er einfach den Code bearbeiten, ihn in „geschützt“ ändern und mit seinem Geschäft weitermachen.

Die einzigen wirklichen Ausnahmen hiervon sind, wenn Sie Binär-DLLs in Black-Box-Form an Dritte versenden.Dazu gehören im Wesentlichen Microsoft, diese „Custom DataGrid Control“-Anbieter und vielleicht ein paar andere große Apps, die mit Erweiterbarkeitsbibliotheken ausgeliefert werden.Sofern Sie nicht zu dieser Kategorie gehören, lohnt es sich nicht, sich über solche Dinge Gedanken zu machen.

Im Allgemeinen würde ich Ihre geschützten Mitgliedsvariablen auf den seltenen Fall beschränken, dass Sie auch die vollständige Kontrolle über den Code haben, der sie verwendet.Wenn Sie eine öffentliche API erstellen, würde ich nie sagen.Im Folgenden bezeichnen wir die Mitgliedsvariable als „Eigenschaft“ des Objekts.

Hier ist Ihre Superklasse kann nicht Tun Sie dies, nachdem Sie eine Mitgliedsvariable geschützt statt privat mit Zugriffsfunktionen gemacht haben:

  1. Erstellen Sie träge einen Wert im laufenden Betrieb, wenn die Eigenschaft gelesen wird.Wenn Sie eine geschützte Getter-Methode hinzufügen, können Sie den Wert langsam erstellen und zurückgeben.

  2. wissen, wann die Eigenschaft geändert oder gelöscht wurde.Dies kann zu Fehlern führen, wenn die Oberklasse Annahmen über den Zustand dieser Variablen trifft.Durch das Erstellen einer geschützten Setter-Methode für die Variable bleibt diese Kontrolle erhalten.

  3. Legen Sie einen Haltepunkt fest oder fügen Sie eine Debug-Ausgabe hinzu, wenn die Variable gelesen oder in sie geschrieben wird.

  4. Benennen Sie diese Mitgliedsvariable um, ohne den gesamten Code zu durchsuchen, der sie möglicherweise verwendet.

Im Allgemeinen denke ich, dass es der seltene Fall ist, dass ich die Erstellung einer geschützten Mitgliedsvariablen empfehlen würde.Es ist besser, ein paar Minuten damit zu verbringen, die Eigenschaft durch Getter/Setter verfügbar zu machen, als Stunden später einen Fehler in einem anderen Code aufzuspüren, der die geschützte Variable geändert hat.Darüber hinaus sind Sie gegen das Hinzufügen zukünftiger Funktionen (z. B. Lazy Loading) versichert, ohne dass abhängiger Code beschädigt wird.Es ist schwieriger, es später zu tun als jetzt.

Auf Entwurfsebene könnte es angemessen sein, eine geschützte Eigenschaft zu verwenden, aber für die Implementierung sehe ich keinen Vorteil darin, diese einer geschützten Mitgliedsvariablen zuzuordnen, statt Zugriffs-/Mutatormethoden.

Geschützte Mitgliedsvariablen haben erhebliche Nachteile, da sie dem Clientcode (der Unterklasse) effektiv Zugriff auf den internen Status der Basisklasseklasse ermöglichen.Dies verhindert, dass die Basisklasse ihre Invarianten effektiv verwaltet.

Aus dem gleichen Grund erschweren geschützte Mitgliedsvariablen das Schreiben von sicherem Multithread-Code erheblich, es sei denn, sie sind garantiert konstant oder auf einen einzelnen Thread beschränkt.

Accessor/Mutator-Methoden bieten bei Wartung erheblich mehr API-Stabilität und Implementierungsflexibilität.

Wenn Sie ein OO-Purist sind, arbeiten/kommunizieren Objekte außerdem durch das Senden von Nachrichten und nicht durch das Lesen/Festlegen des Status.

Im Gegenzug bieten sie nur sehr wenige Vorteile.Ich würde sie nicht unbedingt aus dem Code einer anderen Person entfernen, aber ich selbst verwende sie nicht.

Das Hauptproblem für mich ist, dass Sie, sobald Sie eine Variable geschützt haben, keine Methode in Ihrer Klasse zulassen können verlassen darauf, dass sein Wert innerhalb eines Bereichs liegt, da eine Unterklasse ihn immer außerhalb des Bereichs platzieren kann.

Wenn ich beispielsweise eine Klasse habe, die die Breite und Höhe eines darstellbaren Objekts definiert, und diese Variablen geschützt mache, kann ich beispielsweise keine Annahmen über das Seitenverhältnis treffen.

Im Grunde kann ich das niemals Treffen Sie diese Annahmen zu jedem Zeitpunkt ab dem Zeitpunkt, an dem der Code als Bibliothek veröffentlicht wird, denn selbst wenn ich meine Setter aktualisiere, um das Seitenverhältnis beizubehalten, habe ich keine Garantie dafür, dass die Variablen über die Setter festgelegt werden oder über die Getter im vorhandenen Code darauf zugegriffen wird.

Auch keine Unterklasse meiner Klasse kann diese Garantie übernehmen, da sie die Variablenwerte auch nicht erzwingen kann. auch wenn das der ganze Sinn ihrer Unterklasse ist.

Als Beispiel:

  • Ich habe eine Rechteckklasse, in der Breite und Höhe als geschützte Variablen gespeichert werden.
  • Eine offensichtliche Unterklasse (in meinem Kontext) ist eine „DisplayedRectangle“-Klasse, deren einziger Unterschied darin besteht, dass ich die Breiten und Höhen auf gültige Werte für eine grafische Anzeige beschränke.
  • Aber das ist jetzt unmöglich, seit meiner DisplayedRectangle-Klasse kann nicht Diese Werte werden wirklich eingeschränkt, da jede Unterklasse davon die Werte direkt überschreiben könnte, während sie weiterhin als DisplayedRectangle behandelt wird.

Indem ich die Variablen auf privat beschränke, kann ich dann das gewünschte Verhalten durch Setter oder Getter erzwingen.

In den meisten Fällen ist die Verwendung von protected gefährlich, da dadurch die Kapselung Ihrer Klasse beschädigt wird, was durchaus durch eine schlecht gestaltete abgeleitete Klasse beeinträchtigt werden könnte.

Aber ich habe ein gutes Beispiel:Nehmen wir an, Sie können eine Art generischen Container verwenden.Es verfügt über eine interne Implementierung und interne Zugriffsfunktionen.Sie müssen jedoch mindestens drei öffentlichen Zugriff auf die Daten gewähren:Karte, hash_map, vektorähnlich.Dann haben Sie so etwas wie:

template <typename T, typename TContainer>
class Base
{
   // etc.
   protected
   TContainer container ;
}

template <typename Key, typename T>
class DerivedMap     : public Base<T, std::map<Key, T> >      { /* etc. */ }

template <typename Key, typename T>
class DerivedHashMap : public Base<T, std::hash_map<Key, T> > { /* etc. */ }

template <typename T>
class DerivedVector  : public Base<T, std::vector<T> >        { /* etc. */ }

Ich habe diese Art von Code vor weniger als einem Monat verwendet (der Code stammt also aus dem Speicher).Nach einigem Nachdenken bin ich der Meinung, dass der generische Base-Container zwar eine abstrakte Klasse sein sollte, auch wenn er recht gut funktionieren kann, da die direkte Verwendung von Base so mühsam wäre, dass er verboten werden sollte.

Zusammenfassung Somit verfügen Sie über geschützte Daten, die von der abgeleiteten Klasse verwendet werden.Dennoch müssen wir die Tatsache berücksichtigen, dass die Basisklasse abstrakt sein sollte.

Kurz gesagt, ja.

Geschützte Mitgliedsvariablen ermöglichen den Zugriff auf die Variable von allen Unterklassen sowie allen Klassen im selben Paket.Dies kann insbesondere bei schreibgeschützten Daten sehr nützlich sein.Ich glaube jedoch nicht, dass sie jemals notwendig sind, da jede Verwendung einer geschützten Mitgliedsvariablen mithilfe einer privaten Mitgliedsvariablen und einiger Getter und Setter repliziert werden kann.

Nur für die Aufzeichnung, nach Punkt 24 von "Exceptional C ++", in einem der Fußnoten, geht Sutter "nie eine Klasse, die eine öffentliche oder geschützte Mitgliedsvariable hat.Rechts?(Ungeachtet des schlechten Beispiels einiger Bibliotheken.)“

Ausführliche Informationen zu .Net-Zugriffsmodifikatoren Gehe hier hin

Es gibt keine wirklichen Vor- oder Nachteile geschützter Mitgliedsvariablen. Es kommt nur darauf an, was Sie in Ihrer spezifischen Situation benötigen.Im Allgemeinen ist es üblich, Mitgliedsvariablen als privat zu deklarieren und den Zugriff von außen über Eigenschaften zu ermöglichen.Auch einige Tools (z.B.Einige O/R-Mapper erwarten, dass Objektdaten durch Eigenschaften dargestellt werden und erkennen keine öffentlichen oder geschützten Mitgliedsvariablen.Wenn Sie jedoch wissen, dass Ihre Unterklassen (und NUR Ihre Unterklassen) auf eine bestimmte Variable zugreifen sollen, gibt es keinen Grund, sie nicht als geschützt zu deklarieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top