Get/Set
-
Es geht darum Selektoren grundsätzlich zu reduzieren an Stellen wo sie unnötig sind. Wenn du 4 Methoden hast:
getFoo
setFoo
getFooBar
setFooBardann betreibst du nicht gerade information hiding, weil der Benutzer dadurch weiß: "Ah, die Klasse hat also ein Foo und ein FooBar." Damit hast du unter Umständen schon zu viel von deiner Implementation preis gegeben. Das ist im Prinzip nicht viel besser als public-Variablen. An vielen Stellen kann/muss man allerdings getter und setter benutzen. Aber weniger ist manchmal halt mehr.
PS: HumeSikkins hat neulich einen interessanten Artikel dazu gepostet.
EDIT: Habe ihn gefunden...
http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html?
-
Der Artikel trifft einen wesentlichen Punkt: Kapselung von Objekten.
Allen Holub: "... it's best to minimize data movement as much as possible. My experience is that maintainability is inversely proportionate to the amount of data that moves between objects."
Aber, wenn man schon die getadelten Akzessoren bastelt, dann bitte klar erkennbar, damit man diese im Sourcecode mit Suche nach setX/getX auch alle leicht findet.
Ich denke, wir sind da prinzipiell der gleichen Meinung. Alles andere ist Geschmacksache.
-
MaSTaH schrieb:
Es geht darum Selektoren grundsätzlich zu reduzieren an Stellen wo sie unnötig sind. Wenn du 4 Methoden hast:
getFoo
setFoo
getFooBar
setFooBardann betreibst du nicht gerade information hiding, weil der Benutzer dadurch weiß: "Ah, die Klasse hat also ein Foo und ein FooBar."
Das ist so nicht richtig. Wenn ich eine Klasse für komplexe Zahlen habe und eine Methode setRealTeil() anbiete, weiss der Anwender der Klasse trotzdem nicht, ob ich die Zahl in Polarkoordinaten speichere oder als Real- und Imaginär- Teil speichere, oder eine ganz andere Möglichkeit verwende.
Und mir ist völlig schleierhaft, inwieweit dann ein überladenes realTeil() die Situation verbessern soll.
-
Optimizer schrieb:
Und mir ist völlig schleierhaft, inwieweit dann ein überladenes realTeil() die Situation verbessern soll.
garnicht. hat auch keiner behauptet.
es geht hier nur darum was schöner ist
setFoo/getFoo
oder
Foo() überladen
-
alternativ wäre noch set_foo() und foo(). So mach ich's.
-
sry... aber das find ich verdammt sinnlos!
Ich bin für setX getX, weil das einfach für den DAU der klassen geeigneter ist. Ansonsten verliert so mancher den überblick....
-
Optimizer schrieb:
Das ist so nicht richtig. Wenn ich eine Klasse für komplexe Zahlen habe und eine Methode setRealTeil() anbiete, weiss der Anwender der Klasse trotzdem nicht, ob ich die Zahl in Polarkoordinaten speichere oder als Real- und Imaginär- Teil speichere, oder eine ganz andere Möglichkeit verwende.
Und mir ist völlig schleierhaft, inwieweit dann ein überladenes realTeil() die Situation verbessern soll.Ich glaube wir haben mal wieder ziemlich aneinander vorbei geredet. Ich sprach von dem grundsätzlichen Sinn/Unsinn von verräterischen Selektoren und du von der Namensgebung. Um auf dein Beispiel mit der Klasse für die komplexen Zahlen zurück zu kommen: Es ist sicherlich sinnvoll getter/setter für Real- und Imaginärteil, bzw. für Betrag und Argument anzubieten. Die Namensgebung ist Sache des persönlichen Stils. Es gibt Argumente die für die überladene Version sprechen und solche dir für das get/set-Präfix sprechen. Ich persönlich finde es sinnvoller mir einen Namen zu überlegen der die Aktion beschreibt und über die Implementation null aussagt, z.B. anstatt auto.setFarbe(...) einfach auto.lackiere (blödes Beispiel, aber es sollte klar sein was ich meine
). Wenn mir keiner einfällt bevorzuge ich persönlich getFoo/setFoo als Präfix anstatt foo zu überladen.
-
nu is aber gut!
-
Aehm SOrry, koennt mir mal einer auf die Spruenge Helfen ?
Sinn/Unsinn von verräterischen Selektoren
Damit hast du unter Umständen schon zu viel von deiner Implementation preis gegeben.
Wieso sollte ich Internas an einem object verstecken wollen, wenn ich es fuer andere doch irgendwie zugaenglich machen muss/soll ?
Wenn es sich um das selbe Object handelt, krieg ich doch die implementationsdetails soweiso durch den Header raus ?
Wenn ich das verhindern will, nehm ich ne Proxy Klasse (PIMPL Idom) damit muss ich gar nix ueber die impl nach aussen geben ...
Verstehe die Argumentation nur nicht ganz.Ich bin eher der Meinung lieber ein getter/setter mehr als public members. Mann weiss nie, was man spaeter mal zwischenschieben muss, so muss man wenigstens den eignen code nur anfassen, und die schnittstelle ist wesentlich stabiler.
Ob nun get_Kraft() / set_Kraft(x) oder Kraft()/Kraft(x) ist meiner meinung nach totale Geschmackssache. Basic Fans lieben sicher die 2. Variante. Ich arbeite viel mit der ATL, und bekomme da automatisch soweiso immer nen get_ set_ vor generiert, also halt ich mich im allgemeinen lieber daran ....
Ciao ...
-
Lies doch bitte einfach den Artikel.
getter und setter sollen überlegt eingesetzt werden! Denn viele Leute verwenden für jede member variable auch gleich getter und setter.
Und niemand redet von public Variablen.BTW: wenn man die internas einer Klasse erfahren will, dann kann man sie erfahren. es geht bei information hiding nicht darum die informationen gegen mutwillige angriffe zu schützen.
-
RHBaum schrieb:
Ob nun get_Kraft() / set_Kraft(x) oder Kraft()/Kraft(x) ist meiner meinung nach totale Geschmackssache. Basic Fans lieben sicher die 2. Variante.
Dann waren die Leute vom Standardisierungskommitee wahrscheinlich Basic-Fans. Es gibt in der Standardlibrary zwar ein paar Funktionen, die mit get anfangen ... aber ich bezweifle, dass get, getline von istream oder get vom auto_ptr wirklich in das Standardraster der get-Funktionen rein passen
Einzige Ausnahme: ios_base::getloc.
Ansonsten herrschen eher Namen wie name, what, size, length, flags, begin, end vor. Oder auch rdbuf.
-
@Shade
Lies doch bitte einfach den Artikel.
Dachte das hatt ich schon ...
getter und setter sollen überlegt eingesetzt werden! Denn viele Leute verwenden für jede member variable auch gleich getter und setter.
Was meinst du genau damit ? genau das versteh ich ja ned ... zumindest die disskussion drueber.
Ich mach alle members private/protected . Ist das Ok ?
Fuer alle variablen, die ich von aussen aendern muss/kann darf schreib ich setter ! Falsch ?
Fur alle variablen, die ich von aussen lesen muss, schreib ich getter. Falsch ?
Und wenn eine einzelne andere Klasse viel mit den internas meiner eigenen klasse zu tun hat (Iteratoren z.B), und auch speziell auf die verwaltung meiner klasse ausgelegt ist, dann mach ich die andere Klasse zum "friend" und vermeide so paar zusaetzliche getter und setter ...Ciao ...
-
@Bashar Jo stimmt
Dann sind aber die MFC Progger bei MS keine VB Fans ! :p die z.B. lieben Get und Set ueber allesUnd ueber intuitive Namensvergabe laesst sich echt streiten ....
Beispiel ...
GetCount() ... Aehm welcher Container unterstuetzt SetCount(x) ???
size() ... Naja, schon besser ... aber warum Size und ned count ??? ... will ich anzahl oder groesse (ind was ) ? Als STL Newbie hatt ich echt probleme mit zu begreifen, das size() die aktuelle Anzahl der elemente und ned die momentan allocierte Groesse eines Containers ist .
Ich haett count() genommen ...Ciao ...
-
Man hätte auch length verwenden können, wie einige andere Sprachen oder elements ... .
Fuer alle variablen, die ich von aussen aendern muss/kann darf schreib ich setter ! Falsch ?
Klar erkannt. Falsch! Wenn du sie ändern musst, ok, aber wie oft kommt es vor, dass du direkt ein Attribut ändern musst. Wenn du Sie ändern kannst? Das kannst du immer. Schwachsinn. Darf? Du darfst es, sobald es eine Methode gibt, mit der du es machen kannst.
-
kingruedi schrieb:
Ich benutze die 2. Methode und finde nicht, dass diese verwirrt. Man wird ja als Programmierer schon den Unterschied zwischen
foo.kraft(1); //und std::cout << foo.kraft() << std::endl;
erkennen. Wozu ich da extra get oder set vorschreiben sollte ist mir schleierhaft.
Was machst du wenn foo's kraft von etwas abhängig ist? Etwas was du erst übergeben musst?
-
Ist es denn dann noch eine Getter-Methode? Ich würd's dann eher calcForce() o.ä. nennen...
-
finix schrieb:
Was machst du wenn foo's kraft von etwas abhängig ist? Etwas was du erst übergeben musst?
Was meinst Du?
Inwiefern sollte sich diese Methode dann von setKraft() oä unterscheiden?
-
Cocaine schrieb:
Ich würd's dann eher calcForce()
Hm. Stimmt eigentlich. Aber trotzdem. Wenn du irgendwie mehrere Kräfte oder sonstwas hast und die über nen Index abfragen möchtest wirds auch kritisch.
nman schrieb:
Inwiefern sollte sich diese Methode dann von setKraft() oä unterscheiden?
Es ging um die Methode ohne Prefix.
-
Helium schrieb:
Fuer alle variablen, die ich von aussen aendern muss/kann darf schreib ich setter ! Falsch ?
Klar erkannt. Falsch! Wenn du sie ändern musst, ok, aber wie oft kommt es vor, dass du direkt ein Attribut ändern musst. Wenn du Sie ändern kannst? Das kannst du immer. Schwachsinn. Darf? Du darfst es, sobald es eine Methode gibt, mit der du es machen kannst.
Äh hallo? irgendwie wird mir der Standpunkt hier nicht ganz klar. Ich bin absoluter Verfechter von Zugriffsmethoden. Und zwar konsequent auch für Attribute die nur klassenintern verwendet werden. Ich würde Shades Aussage eher umkehren: Das nicht verwenden von Set/Get-Methoden sollte mit Bedacht gewählt werden.
Wieso? Ganz einfach: Nur Get/Set Methoden garantieren mir, dass ich die Klasseninterna jederzeit beliebig umkrempeln und ergänzen kann, wies grad spass macht, ohne die ganzen Zugriffe auf das Objekt umbauen zu müssen.
Beispiel:
Ich habe ein Doc/View System mit den Klassen TmyDocument und TmyView. Beide gehören in einen Texteditor, wobei TmyView zur Anzeige des Textes in TmyDocument dient. TmyDocument stellt den Text in der Variable "MyText" zur Verfügung.Nun wünscht man sich noch eine Möglichkeit definierte Revisionen zu erstellen. Um die Einfachheit der Bedieung sicherzustellen soll die Revisionskontrolle über ein weiteres Panel ermöglicht werden und an TmyView so wenig wie möglich rumgebaut werden.
Wo realisiert man nun sinnvoller Weise einen Revisionsspeicher? Innerhalb des Dokuments würde ich mal behaupten.Wenn ich hier nun allerdings durch (fadenscheinige) Performance-Gründe die get-Methode (ebenso wie die Set-methode) spare, ist es mir nicht möglich, den Klasseninternen Speicher so umzubauen, dass ich zu guter Letzt nicht mind. 1 mal den Text doppelt im Speicher habe, weil ich ja die Revisionskontrolle habe, welche unter Umständen den zu speichernden Text speisen muss. Das erweiterte Interface? Kein Problem... was zum echten Problem wird ist der Zugriff auf MyText.... da kann ich nur um myText rumbauen und die Effizienz sinkt in den Keller. Wäre hier eine getter-Methode verwendet worden, hätte man ganz einfach die Methode so passend umgebaut, dass sie immer den gewünschten Revisionsstand zurückliefert.
... zugegeben ein konstruiertes Beispiel...vielleicht ist das Beispiel hier etwas naheliegender und entsprechend nachvollziehbarer:
Ich bau ne Anwendung mit ner Klasse XY welche ebenfalls irgendwelche Daten enthält welche sie für Berechnungen benötigt. Zunächst wird die Anwendung single-Threaded betrieben... Keine Synchronisationsprobleme, nix... Hauptsache Power.... also weg mit den 2-3 Takten die jeder Aufruf der Zugriffsmethode benötigt.
Nu kommts aber, dass eine weitere Anwendung gebaut wird, welche eigentlich auf die selbe Klasse zurückgreifen könnte, da sie die selben/ähnliche daten zu verarbeiten hat... diese Anwendung läuft allerdings blöderweise multithreaded... ...egal wird schon gehen.... nach tagelanger Problemsuche von sporadisch auftretenden Fehlern stehts fest: Synchronisationsprobleme.... tja.. was steht an? Umbau der zugreifbaren Variablen auf Zugriffsfunktionen welche CriticalSections verwenden... zack und schon muss ich meine 2. Anwendung - und natürlich auch die Erste um die Kompatibilität sicher zu stellen - umbauen.
Na dann danke.Weitere Beispiele gefällig?
Ich hab noch ein paar auf Lager für all die, welche auf die Idee kommen "Set/Get-Funktionen brauchts ned" oder "sollten mit vorsicht eingesetzt werden". Was allerdings den Kern des Threads (wie man die Get/Set-Funktionen nun implementiert) angeht, muss ich sagen, dass ich alleine schon aus Gründen der Ordnung immer get/set voranstelle... Kostet mich ja nix und schafft eindeutige Verhältnisse.
So, und jetzt geh ich mal Asbestunterwäsche kaufen...
-junix
-
Asbest als atembare Fasern ist krebserregend.