Wie Mehoden definieren, die aufgerufen werden müssen



  • Hallo,

    sagen wir ich habe eine Klasse A, die recht viele Konfigurationsmethoden besitzen.
    Man kann z.B. Anzahl Felder einstellen, Feldgröße usw usw.
    Ich möchte jetzt nicht, dass man alle Parameter gleich im Ctor angeben muss, sonst wird das ein Ctor mit 20 Parametern. Außerdem sieht es im Code unleslich aus:

    A* a = new A("myA", 2, 3, 44.0f, -2, 33, usw.);
    

    Man sieht einfach nicht sofort, für was die Zahlen stehen.
    Drum schreibe ich jede für jeden Set von Parametern einen setter:

    A* a = new A("myA");
    a->setDimension(2, 3);
    a->setCellWidth(44.0f);
    etc...
    

    Das Problem ist nur: Der Benutzer von A MUSS jetzt diese setter aufrufen. Wie könnte man das machen, dass der Benutzer nicht gleich ALLE Params im Ctor übergeben muss, sondern bequem sprechende Setter benutzen kann, diese aber auch wirklich benutzen MUSS?



  • Das kannst du nicht, ausser du überprüfst es im Debug Modus automatisch.

    Du kannst alternativ aber auch einfach deine Parameter sinnvoll gruppieren und dann als struct parameter übergeben.

    Viele Parameter deuten aber auf ein wackeliges Design hin und auf eine Klasse, die zu viel tut.



  • Es gibt einen Weg, der ist aber ein unglaubliches Anti-Pattern:

    Beispielsweise:

    Result r = new A().begin().setFirst('a').setSecond(0x0b).setThird("c").end();
    

    Eine Ab-Art eines Fluent interfaces nur ohne Auswahl:

    class A
    {
    //friend Definitionen
    private:
       char first;
       int second;
       string third;
    
       Result getResult(); 
    
    public:
       A_01 begin() { return new A_01(this); };
    
    }
    
    class A_01
    {
    private:
       A a;
    
    public:
       A_01(A _a) : a(_a) {}
       A_02 setFirst(char value) { a.first = value;return new A_02(a); }
    }
    
    class A_02
    {
    private:
       A a;
    public:
       A_02(A _a) : a(_a) {}
       A_03 setSecond(int value) { a.second= value;return new A_03(a); }
    }
    
    class A_03
    {
    private:
       A a;
    public:
       A_03(A _a) : a(_a) {}
       A_04 setThird(string value) { a.third = value;return new A_04(a); }
    }
    
    class A_04
    {
    private:
       A a;
    public:
       A_04(A _a) : a(_a) {}
       Result end(s) { return a.getResult(); }
    }
    

    Damit man also Result erhält muss man also begin().setFirst('a').setSecond(0x0b).setThird("c").end() aufrufen. Also genau das was du wolltest.

    Kannst natürlich auch die Methoden in beliebiger Reihenfolge aufrufen lassen, vergrößert den Code jedoch ein klein wenig. 🙄


Anmelden zum Antworten