1878 Stimmen

Warum Getter und Setter/Accessors verwenden?

Was ist der Vorteil der Verwendung von Gettern und Settern - die nur abfragen und setzen - anstatt einfach öffentliche Felder für diese Variablen zu verwenden?

Wenn Getter und Setter jemals mehr tun als nur das einfache Get/Set, kann ich dies sehr schnell herausfinden, aber ich bin nicht 100% klar, wie:

public String foo;

schlechter ist als:

private String foo;
public void setFoo(String foo) { this.foo = foo; }
public String getFoo() { return foo; }

Ersteres hingegen erfordert viel weniger Standardcode.

8 Stimmen

10 Stimmen

Natürlich ist beides gleich schlecht, wenn das Objekt keine zu ändernde Eigenschaft benötigt. Ich würde lieber alles privat machen, und dann Getter hinzufügen, wenn es nützlich ist, und Setter, wenn es nötig ist.

31 Stimmen

Google "accessors are evil"

0voto

Obwohl nicht üblich für Getter und Setter, kann die Verwendung dieser Methoden auch in AOP/Proxy-Muster verwendet werden. z.B. für die Prüfung von Variablen können Sie AOP verwenden, um die Aktualisierung eines beliebigen Wertes zu prüfen. Ohne Getter/Setter ist es nicht möglich, außer man ändert den Code überall. Ich persönlich habe AOP nie dafür verwendet, aber es zeigt einen weiteren Vorteil der Verwendung von Getter/Setter.

0voto

jfritz42 Punkte 5775

Ein relativ moderner Vorteil von Gettern/Settern ist, dass sie das Durchsuchen von Code in getaggten (indizierten) Code-Editoren erleichtern. Wenn Sie z.B. sehen wollen, wer ein Element setzt, können Sie die Aufrufhierarchie des Setters öffnen.

Ist das Mitglied hingegen öffentlich, ist es mit den Tools nicht möglich, den Lese-/Schreibzugriff auf das Mitglied zu filtern. Sie müssen sich also durch alle Verwendungen des Mitglieds kämpfen.

0voto

Jonathan Punkte 5990

Wenn Sie eine schreibgeschützte Variable benötigen, aber nicht wollen, dass der Client die Art des Zugriffs auf die Variable ändern muss, können Sie diese Vorlagenklasse verwenden:

template<typename MemberOfWhichClass, typename primative>                                       
class ReadOnly {
    friend MemberOfWhichClass;
public:
    template<typename number> inline bool   operator==(const number& y) const { return x == y; } 
    template<typename number> inline number operator+ (const number& y) const { return x + y; } 
    template<typename number> inline number operator- (const number& y) const { return x - y; } 
    template<typename number> inline number operator* (const number& y) const { return x * y; }  
    template<typename number> inline number operator/ (const number& y) const { return x / y; } 
    template<typename number> inline number operator<<(const number& y) const { return x << y; }
    template<typename number> inline number operator^(const number& y) const  { return x^y; }
    template<typename number> inline number operator~() const                 { return ~x; }
    template<typename number> inline operator number() const                  { return x; }
protected:
    template<typename number> inline number operator= (const number& y) { return x = y; }       
    template<typename number> inline number operator+=(const number& y) { return x += y; }      
    template<typename number> inline number operator-=(const number& y) { return x -= y; }      
    template<typename number> inline number operator*=(const number& y) { return x *= y; }      
    template<typename number> inline number operator/=(const number& y) { return x /= y; }      
    primative x;                                                                                
};      

Beispiel Verwendung:

class Foo {
public:
    ReadOnly<Foo, int> cantChangeMe;
};

Denken Sie daran, dass Sie auch bitweise und unäre Operatoren hinzufügen müssen! Dies ist nur der Einstieg für Sie

0 Stimmen

Bitte beachten Sie, dass die Frage ohne Berücksichtigung einer bestimmten Sprache gestellt wurde.

-1voto

ebt Punkte 1360

Ich wollte ein Beispiel aus der Praxis veröffentlichen, das ich gerade fertiggestellt habe:

Hintergrund - Ich verwende Hibernate Tools, um die Mappings für meine Datenbank zu generieren, eine Datenbank, die ich im Laufe der Entwicklung verändere. Ich ändere das Datenbankschema, stoße die Änderungen an und lasse dann die Hibernate-Tools laufen, um den Java-Code zu generieren. Alles ist gut und schön, bis ich diesen zugeordneten Entitäten Methoden hinzufügen möchte. Wenn ich die generierten Dateien ändere, werden sie jedes Mal überschrieben, wenn ich eine Änderung an der Datenbank vornehme. Also erweitere ich die generierten Klassen wie folgt:

package com.foo.entities.custom
class User extends com.foo.entities.User{
     public Integer getSomething(){
         return super.getSomething();             
     }
     public void setSomething(Integer something){
         something+=1;
         super.setSomething(something); 
     }
}

Was ich oben getan habe, ist, die vorhandenen Methoden der Superklasse mit meiner neuen Funktionalität (something+1) zu überschreiben, ohne die Basisklasse jemals zu berühren. Dasselbe Szenario, wenn Sie eine Klasse vor einem Jahr geschrieben haben und zu Version 2 übergehen wollen, ohne Ihre Basisklassen zu ändern (Test-Albtraum). hoffentlich hilft das.

5 Stimmen

"Was ich oben getan habe, ist, die bestehenden Methoden der Superklasse mit meiner neuen Funktionalität zu überschreiben." Mit einer Funktionalität, von der wir alle hoffen, dass sie bereits für die alte Schnittstelle ordnungsgemäß dokumentiert war, nicht wahr? Andernfalls haben Sie gerade gegen die LSP verstoßen und eine stille, bahnbrechende Änderung eingeführt, die vom Compiler abgefangen worden wäre, wenn keine Getter/Setter in Sicht gewesen wären.

0 Stimmen

@R.MartinhoFernandes "... und dann Hibernate-Tools ausführen, um den Java-Code zu generieren": Hier geht es nicht darum, das Verhalten einer Klasse zu ändern, sondern darum, ein beschissenes Tool zu umgehen. Vielleicht war der Vertrag (der sich in diesem Fall in der Unterklasse befindet) immer für diese "Überraschung" gedacht. Könnte aber ein Argument für has-a statt is-a sein.

0 Stimmen

Mir ist nicht klar, was Sie erreichen, wenn Sie die Eigenschaften der Oberklasse nicht direkt verwenden.

-1voto

luke1985 Punkte 2245

Ich werde den Code für sich selbst sprechen lassen:

Mesh mesh = new Mesh();
BoundingVolume vol = new BoundingVolume();
mesh.boundingVolume = vol;
vol.mesh = mesh;
vol.compute(); 

Gefällt er Ihnen? Hier ist mit den Setzern:

Mesh mesh = new Mesh();
BoundingVolume vol = new BoundingVolume();
mesh.setBoundingVolume(vol);

5 Stimmen

Sie haben die Frage nicht beantwortet, die lautete: "Was ist der Vorteil der Verwendung von Gettern und Settern - die nur get und set ..." Ihr Beispiel ist nicht dieser Fall, und daher trifft Ihre Antwort nicht auf diese Frage zu.

0 Stimmen

Ich denke, die Semantik der angegebenen Codebeispiele ist völlig unterschiedlich. Das erste Beispiel erzeugt auch eine zirkuläre Referenz: mesh.boundingVolume.mesh == mesh

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X