Etwas, worüber ich vorher wirklich nicht nachgedacht habe (AS3-Syntax):
private var m_obj:Object;
protected function get obj():Object
{
return m_obj;
}
private var m_str:String;
protected function get str():String
{
return m_str;
}
Zumindest Unterklassen können m_obj oder m_str nicht setzen (obwohl sie m_obj noch ändern könnten).
Meine Frage: Ist das nur eklatanter Overkill?
Die Frage dieses Programmierers: Wann oder warum sollte man Getter / Setter für Klasseneigenschaften verwenden, anstatt sie einfach zu öffentlichen Eigenschaften zu machen? wurde als Duplikat vorgeschlagen.
Diese Frage ist anders, da sie nur öffentliche oder private Eigenschaften betrifft und ob eine Eigenschaft mit Getter & Setter umwickelt werden soll. Bei meiner Frage konzentriere ich mich auf geschützte Variablen und darauf, wie erbende Klassen mit diesen Variablen interagieren würden.
Die alternative Implementierung wäre also:
protected var m_obj:Object; //more accessible than a private variable with a protected getter
protected var m_str:String; //more accessible than a private variable with a protected getter
Meine Frage ist ähnlich, weil ich über die Verwendung trivial geschützter Getter spreche, um das Schreiben von Unterklassen in die Variablen zu blockieren , ihnen aber allen anderen Zugriff zu ermöglichen.
In Sprachen wie AS3 können sie sogar Änderungen an veränderlichen Objektvariablen vornehmen, solange die Referenzen selbst nicht geändert werden.
quelle
Antworten:
Oft ist es das, manchmal nicht.
Wenn Sie sich
m_obj
in einem bekannten guten Zustand befinden, wird das Liskov-Substitutionsprinzip geschützt, und Ihr Code bleibt widerstandsfähiger und von höherer Qualität. Manchmal können Sie darauf vertrauen, dass Erben dieses Verhalten respektieren, manchmal nicht (entweder aufgrund des Nutzungsmusters oder der Subtilität des Vertrags, den es implementiert). Obwohl dieser Code / diese Frage auch auf einige der Gründe für "Warum schlägt Clean Code vor, geschützte Variablen zu vermeiden?" Stolpert.quelle
Trivial geschützte Getter haben mindestens zwei praktische Vorteile gegenüber einer exponierten Variablen:
Zum Debuggen sind sie der perfekte Ort, um einen bedingten Haltepunkt zu setzen, der ausgelöst wird, wenn „dieser lustige Wert in Ihr Programm gelangt“. Es ist viel schwieriger, dasselbe Steuerelement zu erhalten, wenn Sie direkt auf den Wert zugreifen.
Zum Verspotten eines Objekts, wenn Sie diese Methode zum Testen von Nachkommen verwenden.
Die Kosten für die Verwendung von Gettern sind praktisch Null, daher gibt es keinen wirklichen Grund, sie nicht zu verwenden. Gibt es?
quelle
public
oderprotected
Attribut des Getters! :-)get x() ... { return _y; }
Niemand würde das jemals tippen, aber es könnte aufgrund eines falschen Ausschneidens und Einfügens passieren.Unabhängig davon, ob Sie Getter oder Feldzugriff verwenden, wird jeder erfahrene Prüfer das Problem in Ihrem Entwurf herausfinden und sich darüber beschweren, dass Ihre Objekte Daten anstelle von Verhalten verfügbar machen.
Beachten Sie, dass das Ansprechen von "geschützt" nicht hilft, da der Zweck der Vererbung darin besteht, das Anpassen / Einstellen des Verhaltens des übergeordneten Elements ( LSP ) durch Unterklassen zu ermöglichen und nicht das wahllose Durcheinander mit übergeordneten Daten zu rechtfertigen. Wie Bertrand Meyer es ausdrückt,
Die Argumentation "Getter sind böse" gilt unabhängig davon, ob Sie
get
explizit buchstabieren oder sie hinter dem Feldzugriff maskieren.Wenn Sie ernsthaft über das Problem besorgt sind, sollten Sie zunächst den Code neu gestalten , um sowohl Getter als auch nicht-privaten Feldzugriff zu vermeiden , anstatt erfolglose Gedankenspiele zu spielen, bei denen der am wenigsten unangemessene Weg ausgewählt wird .
Es lohnt sich noch einmal zu betonen, dass das Problem durch das Verstecken von problematischem Design hinter einer "geschützten" Nebelwand nicht behoben werden kann - Vererbung rechtfertigt solche Tricks nicht. Wenn Sie Ihre Frage umschreiben, bemühen Sie sich, die Dinge so zu gestalten, dass geerbte Klassen überhaupt nicht mit diesen Variablen interagieren - weder über Getter noch über den Feldzugriff. Sagen Sie, fragen Sie nicht :
Ich verbringe Zeit und Mühe damit, zu entscheiden, wie ich lieber Informationen erhalten möchte, und empfehle gegen das klassische Prinzip, dies insgesamt zu vermeiden. Das klingt für mich jetzt nach einem offensichtlichen Overkill .
quelle
Im Falle einer unveränderlichen Klassenimplementierung würde das Schützen Ihrer internen Variablen den von Ihnen festgelegten Vertrag brechen. In diesem Fall wären die geschützten Getter nicht übertrieben und notwendig (obwohl Sie Kopien Ihrer Variablen zurückgeben müssten, keinen Zeiger darauf ).
In veränderlichen Klassen ziehe ich es immer noch vor, Getter / Setter dem direkten Zugriff auf meine internen Variablen zu gewähren. Auf diese Weise können Sie den Umgang mit Ihren internen Variablen nach Belieben ändern, ohne befürchten zu müssen, dass Clientcode beschädigt wird. Stellen Sie sich zum Beispiel vor, Sie haben eine Java-Klasse wie folgt:
Die Erweiterung der Client-Klasse
SomeClass
würde dann direkt darauf zugreifensomeVariable
und sie nach eigenem Ermessen bearbeiten. Dies kann nun zu allen möglichen Problemen führen, wenn diese Klassen nichtsomeVariable
in einem akzeptablen Zustand bleiben. Außerdem, wenn Sie in einer späteren Version entscheiden, die Definition zu ändern ,SomeClass
eine verwenden ,List<Integers>
anstelle einem Arrays, werden Sie dann brechen Kompatibilität mit der bestehenden Code - Basis, die erwarten , dassSomeClass
ein internes Array von habenint
s, keine Listeint
s.Wenn Sie in diesem Fall geschützte Getter verwenden, können Sie diese Änderung vornehmen, ohne einen zuvor festgelegten Vertrag zu brechen.
quelle