Wie würden Sie innerhalb einer Objektmethode auf Objekteigenschaften zugreifen?[geschlossen]

StackOverflow https://stackoverflow.com/questions/126

  •  08-06-2019
  •  | 
  •  

Frage

Was ist die „puristische“ oder „richtige“ Möglichkeit, über eine Objektmethode, die keine Getter/Setter-Methode ist, auf die Eigenschaften eines Objekts zuzugreifen?

Ich weiß, dass Sie von außerhalb des Objekts einen Getter/Setter verwenden sollten, aber von innen würden Sie einfach Folgendes tun:

Java:

String property = this.property;

PHP:

$property = $this->property;

oder würden Sie Folgendes tun:

Java:

String property = this.getProperty();

PHP:

$property = $this->getProperty();

Verzeihen Sie mir, wenn mein Java ein wenig daneben liegt, es ist schon ein Jahr her, seit ich in Java programmiert habe ...

BEARBEITEN:

Es scheint, dass die Leute davon ausgehen, dass ich nur von privaten oder geschützten Variablen/Eigenschaften spreche.Als ich OO lernte, wurde mir beigebracht, Getter/Setter für jede einzelne Eigenschaft zu verwenden, auch wenn sie öffentlich war (und tatsächlich wurde mir gesagt, ich solle niemals eine Variable/Eigenschaft öffentlich machen).Es kann also sein, dass ich von Anfang an von einer falschen Annahme ausgehe.Es scheint, dass die Leute, die diese Frage beantworten, vielleicht sagen, dass man öffentliche Eigenschaften haben sollte und dass diese keine Getter und Setter brauchen, was im Widerspruch zu dem steht, was mir beigebracht wurde und wovon ich gesprochen habe, obwohl das vielleicht diskutiert werden muss Also.Das ist aber wahrscheinlich ein gutes Thema für eine andere Frage ...

War es hilfreich?

Lösung

Das birgt das Potenzial für einen Religionskrieg, aber ich denke, wenn Sie einen Getter/Setter verwenden, sollten Sie ihn auch intern verwenden – die Verwendung beider wird später zu Wartungsproblemen führen (z. B.Jemand fügt einem Setter Code hinzu Bedürfnisse jedes Mal ausgeführt werden, wenn diese Eigenschaft festgelegt wird, und die Eigenschaft wird intern festgelegt, ohne dass dieser Setter aufgerufen wird).

Andere Tipps

Ich persönlich halte es für wichtig, konsequent zu bleiben.Wenn Sie Getter und Setter haben, verwenden Sie diese.Ich würde nur dann direkt auf ein Feld zugreifen, wenn der Accessor viel Overhead hat.Es mag sich anfühlen, als würden Sie Ihren Code unnötig aufblähen, aber es kann Ihnen in Zukunft sicherlich eine Menge Kopfschmerzen ersparen.Das klassische Beispiel:

Später möchten Sie möglicherweise die Funktionsweise dieses Feldes ändern.Vielleicht sollte es spontan berechnet werden, oder vielleicht möchten Sie einen anderen Typ für den Hintergrundspeicher verwenden.Wenn Sie direkt auf Eigenschaften zugreifen, kann eine solche Änderung auf einmal sehr viel Code zerstören.

Ich bin ziemlich überrascht, wie einhellig die Meinung ist getters und Setter sind in Ordnung und gut.Ich schlage den aufrührerischen Artikel von Allen Holub vor.Getter und Setter sind böse".Zugegeben, der Titel soll schockierend sein, aber der Autor bringt berechtigte Argumente vor.

Im Wesentlichen, wenn ja getters Und setters Für jedes einzelne private Feld machen Sie diese Felder so gut wie öffentlich.Es würde Ihnen sehr schwer fallen, den Typ eines privaten Felds zu ändern, ohne dass sich dies auf jede Klasse auswirkt, die das aufruft getter.

Darüber hinaus sollten Objekte aus reiner OO-Sicht auf Nachrichten (Methoden) reagieren, die ihrer (hoffentlich) einzigen Verantwortung entsprechen.Die überwiegende Mehrheit davon getters Und setters für ihre konstituierenden Objekte keinen Sinn ergeben;Pen.dispenseInkOnto(Surface) macht für mich mehr Sinn als Pen.getColor().

Getter und Setter ermutigen Benutzer der Klasse auch, das Objekt nach einigen Daten zu fragen, eine Berechnung durchzuführen und dann einen anderen Wert im Objekt festzulegen, besser bekannt als prozedurale Programmierung.Es wäre besser, wenn Sie dem Objekt einfach mitteilen würden, dass es das tun soll, was Sie ursprünglich vorhatten.auch bekannt als die Informationsexperte Idiom.

Getter und Setter sind jedoch notwendige Übel an der Schichtgrenze – Benutzeroberfläche, Persistenz usw.Eingeschränkter Zugriff auf die Interna einer Klasse, wie das Friend-Schlüsselwort von C++, den paketgeschützten Zugriff von Java, den internen Zugriff von .NET usw Muster der Freundesklasse kann Ihnen dabei helfen, die Sichtbarkeit von zu verringern getters und Setzer nur für diejenigen, die sie brauchen.

Es kommt darauf an, wie die Immobilie genutzt wird.Angenommen, Sie haben ein Studentenobjekt, das über eine Namenseigenschaft verfügt.Sie können Ihre Get-Methode verwenden, um den Namen aus der Datenbank abzurufen, sofern er noch nicht abgerufen wurde.Auf diese Weise reduzieren Sie unnötige Aufrufe der Datenbank.

Nehmen wir nun an, Sie haben einen privaten Ganzzahlzähler in Ihrem Objekt, der zählt, wie oft der Name aufgerufen wurde.Möglicherweise möchten Sie die Get-Methode nicht innerhalb des Objekts verwenden, da dies zu einer ungültigen Zählung führen würde.

PHP bietet unzählige Möglichkeiten, damit umzugehen, einschließlich magischer Methoden __get Und __set, aber ich bevorzuge explizite Getter und Setter.Hier ist der Grund:

  1. Die Validierung kann in Settern (und Gettern) platziert werden.
  2. Intellisense arbeitet mit expliziten Methoden
  3. Keine Frage, ob eine Eigenschaft schreibgeschützt, schreibgeschützt oder schreibgeschützt ist
  4. Das Abrufen virtueller Eigenschaften (d. h. berechneter Werte) sieht genauso aus wie reguläre Eigenschaften
  5. Sie können problemlos eine Objekteigenschaft festlegen, die eigentlich nirgendwo definiert ist und dann nicht dokumentiert wird

Übertreibe ich es hier einfach?

Vielleicht ;)

Ein anderer Ansatz wäre, eine private/geschützte Methode zu verwenden, um das Abrufen tatsächlich durchzuführen (caching/db/usw.), und einen öffentlichen Wrapper dafür, der die Anzahl erhöht:

PHP:

public function getName() {
    $this->incrementNameCalled();
    return $this->_getName();
}

protected function _getName() {
    return $this->name;
}

und dann aus dem Objekt selbst:

PHP:

$name = $this->_getName();

Auf diese Weise können Sie das erste Argument immer noch für etwas anderes verwenden (z. B. zum Senden einer Markierung, ob hier zwischengespeicherte Daten verwendet werden sollen oder nicht).

Ich muss hier den Punkt übersehen: Warum sollten Sie einen Getter innerhalb eines Objekts verwenden, um auf eine Eigenschaft dieses Objekts zuzugreifen?

Um dies zum Schluss zu bringen, sollte der Getter einen Getter aufrufen, der wiederum einen Getter aufrufen sollte.

Ich würde also sagen, dass eine Methode innerhalb eines Objekts direkt auf eine Eigenschaft zugreift, insbesondere wenn man bedenkt, dass der Aufruf einer anderen Methode in diesem Objekt (die ohnehin direkt auf die Eigenschaft zugreift und sie dann zurückgibt) einfach eine sinnlose, verschwenderische Übung ist (oder habe ich die Frage falsch verstanden?). ).

Wenn Sie mit „puristisch“ „größte Kapselung“ meinen, dann deklariere ich normalerweise alle meine Felder als privat und verwende dann this.field innerhalb der Klasse selbst, aber alle anderen Klassen, einschließlich Unterklassen, greifen mithilfe der Getter auf den Instanzstatus zu.

Ich würde sagen, es ist besser, die Zugriffsmethoden sogar innerhalb des Objekts zu verwenden.Hier sind die Punkte, die mir sofort in den Sinn kommen:

1) Dies sollte im Interesse der Aufrechterhaltung der Konsistenz mit Zugriffen außerhalb des Objekts erfolgen.

2) In manchen Fällen könnten diese Zugriffsmethoden mehr tun, als nur auf das Feld zuzugreifen;Möglicherweise führen sie eine zusätzliche Verarbeitung durch (was jedoch selten vorkommt).Wenn dies der Fall ist, würden Sie durch den direkten Zugriff auf das Feld diese zusätzliche Verarbeitung verpassen und Ihr Programm könnte schiefgehen, wenn diese Verarbeitung immer während dieser Zugriffe erfolgen soll

Der puristische OO-Weg besteht darin, beides zu vermeiden und dem zu folgen Gesetz von Demeter durch die Verwendung der Sagen Sie, fragen Sie nicht Ansatz.

Anstatt den Wert der Eigenschaft des Objekts zu ermitteln, was enge Paare Verwenden Sie in den beiden Klassen das Objekt als Parameter, z. B.

  doSomethingWithProperty() {
     doSomethingWith( this.property ) ;
  }

Wenn es sich bei der Eigenschaft um einen nativen Typ handelte, z. B.int, verwenden Sie eine Zugriffsmethode und benennen Sie sie nach der Problemdomäne, nicht nach der Programmierdomäne.

  doSomethingWithProperty( this.daysPerWeek() ) ;

Dadurch können Sie die Kapselung und alle Nachbedingungen oder abhängigen Invarianten beibehalten.Sie können die Setter-Methode auch verwenden, um alle Vorbedingungen oder abhängigen Invarianten beizubehalten. Gehen Sie jedoch nicht in die Falle und nennen Sie sie Setter, sondern greifen Sie bei der Benennung auf das Hollywood-Prinzip zurück, wenn Sie die Redewendung verwenden.

Ich habe festgestellt, dass die Verwendung von Settern/Gettern die Lesbarkeit meines Codes erleichtert.Mir gefällt auch die Kontrolle, die es gibt, wenn andere Klassen die Methoden verwenden und wenn ich die Daten ändere, die die Eigenschaft speichert.

Private Felder mit öffentlichen oder geschützten Grundstücken.Der Zugriff auf die Werte sollte über die Eigenschaften erfolgen und in eine lokale Variable kopiert werden, wenn sie mehr als einmal in einer Methode verwendet werden.Wenn und NUR wenn Sie den Rest Ihrer Anwendung so völlig optimiert, abgerockt und anderweitig optimiert haben, dass der Zugriff auf Werte durch Durchsuchen der zugehörigen Eigenschaften zu einem Engpass geworden ist (und das wird NIEMALS passieren, das garantiere ich), sollten Sie überhaupt anfangen Erwägen Sie, etwas anderes als die Eigenschaften direkt mit ihren Hintergrundvariablen in Berührung zu bringen.

.NET-Entwickler können dies mithilfe automatischer Eigenschaften erzwingen, da Sie zur Entwurfszeit nicht einmal die unterstützenden Variablen sehen können.

Wenn ich die Eigenschaft nicht bearbeite, verwende ich eine get_property() öffentliche Methode, es sei denn, es handelt sich um einen besonderen Anlass, wie z. B. ein MySQLi-Objekt innerhalb eines anderen Objekts. In diesem Fall veröffentliche ich einfach die Eigenschaft und bezeichne sie als $obj->object_property.

Innerhalb des Objekts ist es für mich immer $this->property.

Es kommt darauf an.Es ist mehr eine Frage des Stils als alles andere, und es gibt keine feste Regel.

Ich kann mich irren, weil ich Autodidakt bin, aber ich verwende NIEMALS öffentliche Eigenschaften in meinen Java-Klassen, sie sind immer privat oder geschützt, sodass der Zugriff auf externen Code durch Getter/Setter erfolgen muss.Es ist besser für Wartungs-/Änderungszwecke.Und für den internen Klassencode ...Wenn die Getter-Methode trivial ist, verwende ich die Eigenschaft direkt, aber ich verwende immer die Setter-Methoden, da ich bei Bedarf problemlos Code zum Auslösen von Ereignissen hinzufügen könnte.

Nun, mit der Standardimplementierung der C# 3.0-Eigenschaften scheint Ihnen die Entscheidung abgenommen zu werden.Sie MÜSSEN die Eigenschaft mit dem (möglicherweise privaten) Eigenschaftssetzer festlegen.

Ich persönlich verwende den privaten Member-Behind nur dann, wenn die Nichtbeachtung dazu führen würde, dass das Objekt in einen weniger wünschenswerten Zustand gerät, z. B. bei der Initialisierung oder wenn Caching/Lazy Loading beteiligt ist.

Mir gefällt die Antwort von cmcculloh, aber es scheint, dass die Antwort von am richtigsten ist Greg Hurlman.Verwenden Sie immer Getter/Setter, wenn Sie sie von Anfang an verwendet haben und/oder es gewohnt sind, damit zu arbeiten.

Abgesehen davon finde ich persönlich, dass die Verwendung von Getter/Setter das Lesen des Codes und das spätere Debuggen erleichtert.

Wie in einigen Kommentaren angegeben:Manchmal solltest du es tun, manchmal nicht.Das Tolle an privaten Variablen ist, dass Sie alle Orte sehen können, an denen sie verwendet werden, wenn Sie etwas ändern.Wenn Ihr Getter/Setter etwas tut, was Sie brauchen, verwenden Sie es.Wenn es keine Rolle spielt, entscheiden Sie.

Der umgekehrte Fall könnte sein: Wenn Sie den Getter/Setter verwenden und jemand den Getter/Setter ändert, muss er alle Stellen analysieren, an denen der Getter/Setter intern verwendet wird, um zu sehen, ob dadurch etwas durcheinander gebracht wird.

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