| Code Kitchen Allgemeines Coder-Forum rund um das Programmieren eigenständiger, ausführbarer Programme. |
Diskussion: Get- / Set Methoden im Forum Code Kitchen, in der Kategorie Software Home; Anzeige Hallo, im Informatikunterricht lernt man, dass man nie auf die Attribute direkt zugreifen sollte und statt dessen lieber für ...
![]() |
| | #1 (permalink) |
| Anzeige Hallo, im Informatikunterricht lernt man, dass man nie auf die Attribute direkt zugreifen sollte und statt dessen lieber für jedes Attribut eine "get_attribut_a" und eine "set_attribut_a" Methode schreibt. Ich habe nie wirklich verstanden warum man so etwas tun sollte, da der direkte Zugriff viel weniger Code braucht und auch beim Zugriff ersichtlicher ist. Stimmt es das es üblich ist get und set Methoden in Klassen einzubauen? Falls ja, warum ist das so? Falls ihr nicht wisst was ich meine: direkter Zugriff(Code in der Klasse erübrigt sich): Code: x.input_protocol = "imap" print x.input_protocol Code: def get_input_protocol(self):
return input_protocol
def set_input_protocol(self, p_input_protocol):
input_protocol = p_input_protocol Code: x.set_input_protocol("imap")
print x.get_input_protocol MfG Stein
__________________ Steinhagelvoll | |
| | |
| | #2 (permalink) |
| Senior Member | Eine Antwort ist wohl daß ja eine getter- bzw. setter-Methode ja auch aus mehr als nur dem setzen und zurückgeben der Variable bestehen kann. Beispielsweise könnte man im Setter den übergebenen Wert inhaltlich prüfen bzw. sogar ändern. Im Getter könnte analog dazu der Variableninhalt in irgendeinerweise formatiert zurückgegeben werden. Würde man in einem Programm mal den Getter und mal den direkten Zugriff auf die Variable benutzen kann das zu unschönen Ergebnissen führen. Ergo ist es besser strikt immer die Getter und Setter zu benutzen.
__________________ [HaBo] @ Facebook - Gefällt mir! |
| | |
| HaBOT | - Anzeige - |
| |
| | #3 (permalink) |
| Senior Member Registriert seit: 10.03.07 ![]() Likes: 19 | Ich werf einfach mal den entsprechenden Wikipediaartikel in den Raum: Zugriffsfunktion |
| | |
| | #4 (permalink) |
| Registriert seit: 22.04.08 ![]() Likes: 15 | Abgesehen davon ist der Performancenachteil bei get-/set-Methoden auf einem PC nicht spürbar. Natürlich gibt es auch Gebiete, bei denen man möglichst auf diese Methoden verzichten sollte, nämlich wenn man beispielsweise einen Microcontroller programmiert. Gemessen haben wir das mal an der Ausführungszeit von identischen (Java- bzw. Lejos-)Programmen auf Lego Mindstorms, einmal mit get-/set-Methoden und einmal per direktem Zugriff. |
| | |
| | #5 (permalink) |
| Moderator ![]() Registriert seit: 20.07.05 ![]() ![]() ![]() ![]() ![]() ![]() Likes: 202 | Zum einen kann man mit der OO auch übertreiben (der "getter/setter Wahn" Andererseits - ein praktisches Beispiel, warum Getter/Setter auch in Python nützlich sein können: Der Code bildet eine Art Abhängigkeit in einem Ablauf als Baum ab und versucht diese dann möglichst weit zu vereinfachen, bevor damit weiterer Unfug angestellt wird. Vorläufige Implementierung: Code: class Node(object):
....
class FooNode(Node):
....
def reduce(self):
....
class BarNode(Node):
def reduce(self):
left = self.childs[0].reduce()
right = self.childs[1].reduce()
...
if left == foo:
return BarNode(left)
return FooNode(left, right) Funktioniert erstmal wunderbar - bis man die "reduce" Funktion soweit verfeinert hat, dass sie auch ein "direktes" True/False zurückgibt und man nette AttributeError Exceptions um die Ohren geworfen bekommt Was nun? Jeden Zugriff auf die "childs" mit Try/Except umwrappen == viel zu viel Schreibarbeit. Aber ein Getter-Setter kann dies einem durchaus ersparen: Code: class Node(object):
def get_child(self, n):
if isinstance(self.childs[n], Node):
return self.childs[n]
else:
return WrapperNode(self.childs[n])
class WrapperNode(Node):
def reduce(self):
return self "self.get_child(0)" und hat sich viele Zeilen Code erspart und diesen sogar flexibler gemacht (ok, als Schlangenguru kann man auch __getattr__ der Klasse überschreiben - aber ist zum einen genausoviel Tipparbeit, zum anderen etwas komplizierter in der Handhabung Und bei größeren Projekten versucht man mit Getter/Setter, abgestufter Sichtbarkeit der Methoden/Attribute die Abhängigkeiten zu reduzieren und möglichst klare Schnittstellen zu schaffen. Ein direktes Beschreiben eines Attributes kann dann ganz böse enden, wenn z.B irgendwelche intern en Änderungen daran stattfinden. Stichwort wäre auch "Datenkapselung".
__________________ Noch mal, für alle Pseudo-Geeks: 1+1=0. -> 10 wäre Überlauf! Selig, wer nichts zu sagen hat und trotzdem schweigt. |
| | |
| | #6 (permalink) |
| Registriert seit: 20.07.06 ![]() Likes: 21 | Ich denke getter und setter unterstützen die Philosophie der OOP. Eine Klasse stellt soetwas wie eine Blackbox da. Es ist nicht interesant wie eine Klasse etwas macht sondern es kommt nur darauf an, dass sie es macht. Methoden stellen somit die Schnittstelle der Klasse zur Außenwelt dar. Wenn ich auf Attribute einer Klasse nur über Methoden zugreifen kann, dann ist das einfach eine sauberere Programmierung, als wenn ich wild von außen alle möglichen Attribute direkt ändern kann. |
| | |
| | #7 (permalink) |
| Moderator ![]() Registriert seit: 20.07.05 ![]() ![]() ![]() ![]() ![]() ![]() Likes: 202 | Nunja, der wesentliche Nachteil an gettern/settern ist imho die schlechte Lesbarkeit: "desktop.getMouse().getCoords().getX ()" deutlich umständlicher zu lesen, als desktop.mouse.coords.x oder: mouse.coords.x = 10 vs. "desktop.getMouse().getCoords().setX (10)" Insofern scheinen mir "Properties" ein ganz guter Kompromiss zu sein: Properties (C#) c# Man hat also in der Klasse selbst getter/setter, "nach außen" hin aber angenehmere/lesbare Syntax. (die gibt es im übrigen auch für Python - entweder zum selberbasteln mit "__gettattr__" und "__setattr__" oder als "property" Decorator/Built-in) Edit: wie gesagt, mit OOP kann man auch übertreiben - ich behaupte einfach mal ganz frech, dass hier niemand in der Praxis 100% OOP programmiert bzw. auch es nicht wirklich möchte
__________________ Noch mal, für alle Pseudo-Geeks: 1+1=0. -> 10 wäre Überlauf! Selig, wer nichts zu sagen hat und trotzdem schweigt. |
| | |
| | #8 (permalink) |
| Registriert seit: 03.05.07 ![]() ![]() Likes: 50 | Noch einen kleinen Tipp: Falls man in die Situation kommt einen Haufen Getter und Setter in einem einzigen Objekt einzubauen sollte man die Struktur überdenken. Objektorientierung ist ja wirklich schön und gut, nur sollte man sie dort einsetzen, wo sie angebracht ist. Kurz gefasst: Probleme innerhalb eines Moduls abgekapselt lösen. Wenn man aber eben viele Getter und Setter benötigt ist entweder das Modul nicht wirklich abgekapselt vom Rest oder das Objekt ist eigentlich nur eine simple Datenstruktur(-ansammlung), welche in ein objektorientiertes Korsett gezwungen wird. Wobei Datenstruktur natürlich nicht böse sind, braucht man auch. Man sollte nur wissen wo man was hat bzw. einsetzt. mfg benediktibk |
| | |
| | #9 (permalink) |
| Registriert seit: 17.04.06 ![]() Likes: 3 | Natürlich sind Getter und Setter grundsätzlich was Gutes. Oft bildet eine Klasse aber auch 1:1 eine SQL-Tabelle ab wo jedes Member eine Column ist. Da kann man meiner Meinung nach durchaus alle Member public machen. Aber so einen Code lässt man sich meist wohl generieren.
__________________ http://chm0815.blogspot.com |
| | |
| | #10 (permalink) | |
| Member of Honour ![]() | Zitat:
entweder man verwendet grundsätzlich Getter und Setter oder man lässt es bleiben. Aber eine Member-Variable per getter/setter und die nächste direkt - das finde ich absolut abartig... Da lieber schreibe ich mir ein kleines Auto-Code-Generator-Script, welches mir die Getter und Setter automatisch schreibt und ich nur noch bei den entsprechenden Settern die Eingaben nachträglich per Hand validieren muss, als dass ich direkten Zugriff auf meine Attribute zulasse... Wir sind @work gerade dabei, das Shop-System auf eine komplett eigene Lösung umzubauen, welche nur noch auf die Datenbank-Struktur des xtCommerce zugreift... Da gehen wir noch 'nen Schritt weiter und machen nicht nur getter/setter zur Pflicht sondern haben uns - damit es einfacher wird, den Code von Kollegen zu lesen - sogar ne ganz detaillierte Coding-Guideline erarbeitet: Namenskonvention für Funktionen/Klassen/Methoden/Attibute, selbst Klammersetzung und Einrückung sind definiert und die Tatsache, dass das schließende PHP-Tag verboten ist und wie detailiert die DocBlocks zu schreiben sind, etc. Das klingt für den Anfang vielleicht etwas over-the-top, aber wenn du im Team arbeitest und Code von Kollegen gegenliest, ist es echt wesentlich angenehmer, wenn es einheitliche Richtlinien gibt. | |
| | |
| | #11 (permalink) | |
| Moderator ![]() Registriert seit: 20.07.05 ![]() ![]() ![]() ![]() ![]() ![]() Likes: 202 | Zitat:
![]() Denn striktes OOP bedeutet eigentlich: alles ist ein Objekt bzw. wird wie eins behandelt. Konsequenterweise müsste man dann auch Zahlen als Objekte behandeln -> alle Operationen darauf nur mit Methoden/Nachrichten durchführen. Also statt 1+2*3 sowas schreiben: 1.add(2.mul(4)) oder mit "Syntaxsuggar": 1+(2*(3)) (Die Klammern gehören zum Aufruf der Methode und natürlich gibt es dann keinen Punkt-Vor-Strich). Das ist auf Dauer genauso umständlich, wie stricktes "alles ist ein Ausdruck"/"alles ist eine Funktion"/"alles ist ein rel. Algebraausdruck aka SQLQuery" Um ein reales Beispiel zu bringen: ein serieller Ablauf/Protokoll, der in die Objektform "gequetsch" behandelt wird, oder Event-Handling "auf OOP Basis" (das Objekt stellt dann quasi eine große State-Maschine dar ) ist nicht minder grausam zu lesen und zu warten. Insofern wäre ich eher benedikts Meinung - Einsetzen, wo es angebracht ist und nicht als Allheilmittel ansehen
__________________ Noch mal, für alle Pseudo-Geeks: 1+1=0. -> 10 wäre Überlauf! Selig, wer nichts zu sagen hat und trotzdem schweigt. | |
| | |
| | #12 (permalink) |
| Ein weiterer Vorteil von Settern und Gettern ist es, dass man den Zugriff auf Attribute einschränken oder durch Proxies ersetzen kann. Wenn du direkten Variablenzugriff hast, kannst du diesen durch Subklassen nicht verändern. Mit Settern und Gettern trennst du eine Klasse in zwei Komponenten: Eine Schnittstellen (Funktions-Deklarationen) und eine Logikkomponente (Member-Variablen und Implementierung). Du kannst dann jederzeit durch Ableitung die Logik verändern, ohne die Schnittstelle modifizieren zu müssen. Zwei Beispiele: Code: class Bar {
private int foo;
public Bar(int foo) {
this.foo = foo;
}
public int getFoo() {
return this.foo;
}
public void setFoo(int foo) {
this.foo = foo;
}
}
class UnmodifiableBar extends Bar {
public UnmodifiableBar(int foo) {
super(foo);
}
@Overrides
public void setFoo(int foo) {
throw new UnsupportedOperationException("Unmodifiable, bitches!");
}
} Code: class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
}
class PersonFromDatabase extends Person {
private int id;
public PersonFromDatabase(int dbId) {
super(null, null);
this.id = dbId;
}
public String getName() {
String currentName = getNameFromDatabase(this.id);
return currentName;
}
public void setName(String name) {
setNameToDatabase(this.id, name);
}
public int getAge() {
int currentAge = getAgeFromDatabase(this.id);
return currentAge;
}
public void setAge(int age) {
setAgeToDatabase(this.id, age);
}
} mfg, metax.
__________________ Wenn keiner zuschaut, teile ich heimlich durch Null! Meine Homepage: Planet Metax | meine Bilder: DeviantArt | Twitter | |
| | |
| | #13 (permalink) |
| Moderator ![]() Registriert seit: 30.09.06 ![]() ![]() ![]() ![]() ![]() ![]() Likes: 441 | Man sollte ggf. bei der OOP auch die verteilte Entwicklung nicht ganz ausser Acht lassen. Da geht es ja u.a. darum, dass ein Entwickler A nicht wissen muss was Entwickler B in seinen Klassen definiert und tut. Wenn Entwickler A in einer Klasse von Entwickler B einen Wert setzt, dann tut er dies über eine Setter-Methode und wenn er einen Wert liest, tut er dies über eine Getter-Methode. Ihn muss dabei nicht kümmern welche Variablen innerhalb der Klasse von Entwickler B angesprochen werden, wie diese heissen oder ob da noch irgendwelche Prüfungen durchgeführt werden. Er muss nur wissen, dass beim Aufruf von Funktion setXY() ein Wert dem ganzen Objekt bekanntgegeben wird und dass er den Wert XY, der im ganzen Objekt bekannt ist, durch Aufruf von Funktion getXY() erfahren kann. Der Entwickler der Klasse hat somit die Freiheit beliebig die Benennungen seiner Variablen zu ändern, während das "Interface" der Klasse gleich bleiben kann. Ausserdem muss er nicht darauf vertrauen, dass Entwickler A schon die richtigen Daten liefern wird, sondern kann dies nochmal explizit prüfen. Allgemein denke ich aber auch, dass man manchmal mit OOP auch gern übertreibt. Sinn macht es imo eigentlich nur, wenn viele Leute an einer Software arbeiten, so dass es kaum möglich ist, dass Entwickler A weiss was Entwickler B tut. Die Entwickler müssen dann nur wissen: Es gibt diese und jene Klassen, die diese und jene Daten verarbeiten können und diese und jene Werte bereitstellen.
__________________ Mein Blog - Mein Job - Diaspora Der Ring uns zu knechten besteht aus 12 Sternen auf blauem Grund. Neue Beiträge im Habo via Twitter - Das HaBo auf FB - Das HaBo bei G+ |
| | |
| | #14 (permalink) |
| Member of Honour ![]() Registriert seit: 28.05.10 ![]() ![]() ![]() ![]() ![]() ![]() Likes: 210 | Code: (alles istObjekt) ifTrue: [ Transcript show: 'Willkommen bei Smaltalk' ] erinner uns doch blos nicht daran ...
__________________ Code: :(){ :|:& };: |
| | |
| | #15 (permalink) |
| Registriert seit: 20.08.11 ![]() Likes: 0 | Man kann getter/setter natürlich auch zweckempfremden um zeit zu sparen. ein kürzlich von mir angewendetes beispiel: Konsolenenanwendung. es geht um einen server. dieser soll statusmeldungen nach dem Schema "<Datum/Uhrzeit> <Nachricht>" ausgeben. das selbe soll gleichzeitig in die datei <Appdata-Verzichnis>\server.log geschrieben werden (dieser Pfad liegt in der Variablen logfile das ließe sich so regeln: VB.NET-Code Code: console.WriteLine(now & "Meldung 1") My.Computer.Filesytem.WriteAllText(logfile,now & "Meldung 1" & vbNewLine,True) console.WriteLine(now & "Meldung 1") My.Computer.Filesytem.WriteAllText(logfile,now & "Meldung 1" & vbNewLine,True) console.WriteLine(now & "Meldung 1") My.Computer.Filesytem.WriteAllText(logfile,now & "Meldung 1" & vbNewLine,True) '... VB.NET-Code Code: Public Property Text as String
Set (Byval value as String)
console.WriteLine(value)
my.Computer.FileSystem.WriteAllText(logfile,now & value & vbnewline, true)
End Set
Get
dim tmp as String = console.ReadLine ' auch sowas ist dann gleich möglich:wink:
my.Computer.FileSystem.WriteAllText(logfile , " >" & tmp & vbNewLine,true)
return tmp
End Get
End Property
Sub Main()
text = "Meldung 1"
text = "Meldung 2"
text = "Meldung 3"
End Sub Ist aber alles Andere als OOP-konform |
| | |
![]() |
| - Anzeige - | |
| |
| Themen-Optionen | |
| Ansicht | |
| |