Propertys statt Getter und Setter Methoden?



  • Mit einigen (vielen?) IDEs kannst du auch automatisch standard-getter/setter generieren lassen.



  • Es gibt auch z.B. (nicht konforme!) Spracherweiterungen.



  • in C# gehts so:

    class MyClass
    {
    private int x;
    public int X
    {
    get
    {
    return x;
    }
    set
    {
    x = value;
    }
    }
    } 
    ...........
    MyClass p = new MyClass();
    
    p.X=6;
    
    int j = p.X;
    


  • PropertyUser schrieb:

    in C# gehts so:

    Da hast du ja in etwa den gleichen Schreibaufwand, wie in C++. 🙄

    Bei der Benutzung musst du hald die get() oder set(...) schreiben. Aber das ist ja kein Weltuntergang. 🙄



  • PropertyUser schrieb:

    in C# gehts so:

    Mit Einrückung wäre es deutlich lesbarer gewesen. Die Propertysyntax von C# reduziert aber nur dann den Schreibaufwand, wenn du die Standardimplementierung verwendest. Ich habe es noch nicht überprüft, aber scheinbar kann man unter C# 3.0 bei trivialen Getter/Setter die Implementierung weglassen:

    class MyClass
    {
      private int x;
      public int X { get; set; } // ka. ob Richtig, hatte es nur mal kurz überflogen
      //...
    }
    

    Properties halte ich nur aus einen Grund für sinnvoll: Das Sparen von "Get" und "Set", und den Zugriff in Form einer Elementsyntax. Es ist jedenfall (bei nichttrivialen Properties) nicht weniger Schreibaufwand.

    cu André



  • Und Properties erhöhen die Kapselung: Ich kann lesend oder schreibend auf eine Eigenschaft zugreifen, ohne wissen zu müssen, ob da jetzt im Hintergrund ein Methodenaufruf stattfindet oder nur eine einfache Zuweisung.
    Ist aber ein rein theoretischer Vorteil, praktisch gesehen bewirkt es aber zumindest, dass man sich bei boolschen Eigenschaften nicht zwischen getXXX(), isXXX() oder hasXXX() entscheiden muss 😉



  • Chewie83 schrieb:

    ...bewirkt es aber zumindest, dass man sich bei boolschen Eigenschaften nicht zwischen getXXX(), isXXX() oder hasXXX() entscheiden muss 😉

    Um genau zu sein verwendet C# intern auch nur Getter und Setter, ich glaube get_xxx und set_xxx.

    cu André



  • Properties reduzieren den Schreibaufwand clientseitig (minimal).

    Library-seitig erhöhen sie manchmal den Schreibaufwand ordentlich. Nämlich dann wenn man alles als Property abbildet was "eine Property sein sollte", und dazu dann diverse Hilfklassen basteln muss (z.B. Collection-Klassen die mit der "Parent-Klasse" kommunizieren).



  • Wobei ich auch schon oft darüber nachgedacht habe, Getter und Setter durch ne Fkt zu ersetzen, die ne (const) ref wiedergibt...

    class Name
    {
    private:
      std::string m_vorname;
      std::string m_nachname;
    public:
    //...ctor...
      std::string& Vorname () {return m_vorname;}
      const std::string& Vorname () const {return m_vorname;}
    };
    

    Ist zwar der gleiche Schreibaufwand, aber hat den Vorteil, dass so etwas besser möglich ist:

    int main ()
    {
    Name name ("vorname", "nachname");
    name.Vorname () += " 2.Vorname";
    }
    

    bb



  • Aber wo bleibt da der Vorteil gegenüber public -Membern? Einheitliche Schnittstelle und Klammersyntax?

    Die Gefahr hierbei ist ja wieder, dass man z.B. durch Seiteneffekte ungewollt die Member verändert, wenn man aber eigentlich nur lesen will...


  • Administrator

    @unskilled,
    Aber sowas ist eher selten. Meistens gibt man dem User zuerst den ganzen String zurück in ein Edit-Feld oder ähnliches und der User verändert den String dann. Am Ende speichert man sowieso wieder den ganzen String.
    Dass es tatsächlich mal ein append gibt, ist bei mir äusserst selten und wenn es einen gibt, dann habe ich meistens eine append_xxx Funktion drin.

    Grüssli



  • unskilled schrieb:

    Ist zwar der gleiche Schreibaufwand, aber hat den Vorteil, dass so etwas besser möglich ist:

    Und den wesentlichen Nachteil das der Code anders als gewohnt, und damit schwerer zu lesen ist. Zudem wird die konstante Referenz nur bei Konstanten Objekt verwendet, die Kapselung zerstört (Jeder kann sich die Referenz merken und beliebig manipulieren...



  • asc schrieb:

    unskilled schrieb:

    Ist zwar der gleiche Schreibaufwand, aber hat den Vorteil, dass so etwas besser möglich ist:

    Und den wesentlichen Nachteil das der Code anders als gewohnt, und damit schwerer zu lesen ist. Zudem wird die konstante Referenz nur bei Konstanten Objekt verwendet, die Kapselung zerstört (Jeder kann sich die Referenz merken und beliebig manipulieren...

    Japp - war erstens noch nen eher unpassendes Beispiel und zweitens hab ich ja auch geschrieben, dass ich es mir immer nur überlegt habe und dann doch jedes mal wieder verworfen habe ^^

    asc schrieb:

    die konstante Referenz nur bei Konstanten Objekt verwendet

    Oo das hab ich noch gar nicht gewusst - dachte bisher eigtl immer, dass der compiler immer versucht, const zu nehmen und erst, wenn er das nicht kann, nimmt er die "normale" fkt?!

    bb



  • Ja eben, ich frage mich wieso man die members nicht einfach öffentlich macht, wenn sie via Get/Set verändert werden dürfen. Ist wohl schlechter Stil? Macht das legendäre Information-Hiding Konzept kaputt!?

    Wäre edel, wenn man member nich nur public/private anlegen könnte, sonder auch ReadOnly, WriteOnly ... und sich so das Get/Set Information Hiding konzept schenkt^^



  • PropertyUser schrieb:

    Ja eben, ich frage mich wieso man die members nicht einfach öffentlich macht, wenn sie via Get/Set verändert werden dürfen. Ist wohl schlechter Stil? Macht das legendäre Information-Hiding Konzept kaputt!?

    Ja, ist schlechter Stil. Der Grund ist dafür das öffentliche Member unkontrolliert manipuliert werden können, man keine Änderungen der Freigabe mehr vornehmen kann ohne die Schnittstelle zu ändern, und auch jegliche Bereichsprüfungen unmöglich werden.

    Nehmen wir mal an du machst folgendes:

    class Adresse {
        public:
            std::string name;
            std::string nachname;
    };
    
    int main()
    {
        Adresse paul;
        paul.name = "Paul";
        paul.name = "Zufall";
    }
    

    Dann kann jeder diese Werte unkontrolliert ändern, und nicht nur das, man kann sich Referenzen auf diese Werte merken, sie speichern und jegliches Geheimnisprinzip wird vernichtet. Gehen wir einen Schritt weiter:

    class Adresse {
        private:
            std::string name;
            std::string nachname;
        public:
            std::string GetName() const { return name; }
            void SetName(std::string const & name) { this->name=name; }
            std::string GetNachname() const { return nachname; }
            void SetNachname(std::string const & nachname) { this->nachname=nachname; }
    };
    

    Im ersten Moment mag dies für dich identisch erscheinen. Aber bereits jetzt gibt es ein paar gravierende Änderungen: Man kann keine Referenz auf die Member mehr anlegen, direkte und unkontrollierte Änderung ist nicht möglich.

    Weiterer Vorteil: Man kann Bereichsprüfungen einbauen ohne die Schnittstelle zu ändern; man kann Die Daten in ein anderes Objekt verschieben und die Klasse durch Delegation dennoch lauffähig halten; man kann den Zugriffsschutz separat für Getter und Setter anpassen.

    PropertyUser schrieb:

    Wäre edel, wenn man member nich nur public/private anlegen könnte, sonder auch ReadOnly, WriteOnly ... und sich so das Get/Set Information Hiding konzept schenkt^^

    ReadOnly: Konstante
    WriteOnly: Zumeist (aber nicht immer) ein Designfehler
    Und Referenzen wären dann dennoch möglich.

    In sofern sind die Properties in C# 3.0 oder C++/CLI doch schon schön: man kann erst einmal die Properties als triviales get/set (ohne weiteren Code) deklarieren und später anpassen.

    Ergo: Bitte unter C++ keine öffentlichen Member verwenden, du verhinderst damit die Codewartung (und ja, es gibt Unterschiede zwischen trivialen Properties bzw. get/set und direkten Memberzugriff).

    cu André
    P.S: Ich durfte die Nachteile öffentlicher Methoden, und Zeiger auf die Member in einem Projekt schon ausbaden, da der vorherige Programmierer an Schreibfaulheit leided.



  • asc schrieb:

    PropertyUser schrieb:

    in C# gehts so:

    [...]

    class MyClass
    {
      private int x;
      public int X { get; set; } // ka. ob Richtig, hatte es nur mal kurz überflogen
      //...
    }
    

    [...]

    Nur kurz eine kleine Korrektur, so sähe das aus:

    class MyClass {
      public int X { /*private*/ get; /*private*/ set; }
      /...
    }
    

    Der Compiler generiert das private Feld selbstständig im Hintergrund. AFAIR ab C# 3.5.



  • SolidOffline schrieb:

    AFAIR ab C# 3.5.

    Ahh... erst in der Zukunft? 😉
    Derzeit aktuell .Net Framework 3.5 und C# 3.0...



  • asc schrieb:

    SolidOffline schrieb:

    AFAIR ab C# 3.5.

    Ahh... erst in der Zukunft? 😉
    Derzeit aktuell .Net Framework 3.5 und C# 3.0...

    Äh, ja richtig, .Net 3.5 hätte es heißen sollen, danke.

    Vielleicht noch ganz interessant in dem Zusammenhang:

    Properties sollte man sowieso nur für triviale Getter/Setter verwenden (einfache Zuweisung), jedenfalls habe ich das mal so irgendwo als Empfehlung in der MSDN gelesen, da die Elementzugriffssyntax (also z.B. myClass.X = 3;) eine einfache Zuweisung mit geringem Performancekostenaufwand suggeriert. Alles was darüber hinausgeht sollte man daher in eigene Funktionen packen, so dass schon anhand der Syntax klar wird, dass das evtl. performancetechnisch mehr kosten könnte. Wobei die Grenze da wohl fließend ist (packe ich x = value * 2 + 4 noch in die Property, oder schon in eine eigene Funktion "SetX"?).



  • SolidOffline schrieb:

    Properties sollte man sowieso nur für triviale Getter/Setter verwenden (einfache Zuweisung), jedenfalls habe ich das mal so irgendwo als Empfehlung in der MSDN gelesen, da die Elementzugriffssyntax (also z.B. myClass.X = 3;) eine einfache Zuweisung mit geringem Performancekostenaufwand suggeriert.

    Wenn trivial in diesem Zusammenhang nur setzen/lesen des Wertes wäre, würde ich (und die Codebeispiele zu WPF) dem widersprechen. Wenn trivial meint, das dort keine Aufwendigen Funktionalitäten enthalten sein sollten, sehe ich das durchaus ähnlich.

    Für mich gehört in die Property:
    a) Setzen/Lesen des Wertes (ggf. indirekt wie bei Proxies)
    b) Wertebereichsprüfungen, sofern diese nicht an einer anderen Stelle sinnvoll sind.
    c) Aufruf von Observern/Changeevents wie z.B. in WPF nicht unüblich.

    cu André



  • asc schrieb:

    Properties halte ich nur aus einen Grund für sinnvoll: Das Sparen von "Get" und "Set", und den Zugriff in Form einer Elementsyntax. Es ist jedenfall (bei nichttrivialen Properties) nicht weniger Schreibaufwand.

    Das geht ja nun am eigentlichen Sinn der Properties so ziemlich vorbei.

    Der eigentliche Vorteil von Properties ist die Persistenz. So funktioniert beispielsweise der Formulardesigner der VCL. Alle Komponenten verfügen über eine Reihe von Properties, die den Status repräsentieren und die im Objektinspektor mittels Reflection angezeigt werden. Wenn eine Komponente auf dem Formular plaziert wird, erstellt der Formulardesigner ein Objekt dieser Komponente im Designer-Modus (die IDE sorgt dafür, daß die Komponente sich auch entsprechend verhält, also nicht wie zur Laufzeit bedienbar ist, sondern z.B. vergrößert, verschoben etc. werden kann). Der Programmierer kann mit Desiger und Objektinspektor über die Properties der Komponente ihren Status festlegen, und beim Speichern wird die Komponente einfach mit den Serialisierungsfunktionen der VCL in die .dfm-Datei gestreamt, die in das Programm als Ressource gelinkt wird. Wird das Programm gestartet, so wird die Komponente aus der .dfm-Datei geladen. So muß der Designer gar nichts weiter über die Komponente wissen: alle nötigen Informationen dafür kann er mittels Reflection erhalten.


Anmelden zum Antworten