Unterklassen zwingen, Methode selbst zu implementieren, wenn Oberklasse Methode ebenfalls implementiert?



  • Hallo!

    Ich arbeite daran, bei einer Reihe von Klassen, die alle von einer gemeinsamen Oberklasse abhängen, eine Selbstüberprüfung bezüglich der Membervariablen zu implementieren. D.h. die Membervariablen müssen gesetzt sein und deren Wertebereiche müssen OK sein.

    Die Idee wäre nun, eine

    public:
    virtual void validate() throws (Exception);
    

    in die Oberklasse einzuführen. Die Unterklassen müssten das dann selbst implementieren, sonst meckert der Compiler. Leider habe ich da zwei Probleme:

    1. Die Oberklasse hat auch Attribute und muss sich selbst überprüfen. Am liebsten "transparent", d.h. ein A::validate() einer Unterklasse A von Oberklasse sollte ganz von alleine ein Oberklasse::validate() beinhalten. Damit man das nicht vergessen kann.
    2. Es gibt noch Zwischenklassen zwischen Oberklasse und den eigentlich verwendeten Klassen A, B, C, ... und auch dort muss eine Selbstüberprüfung stattfinden. Auch die sollte zwingend notwendig sein.

    Lässt sich das irgendwie realisieren? Erst wollte ich in Oberklasse schreiben:

    public:
    virtual void validate() throws (Exception);
    protected:
    void validateOberklasse() throws (Exception) {
    // pruefe dich selbst
    }
    

    und dann hätte man halt dran denken müssen, validateOberklasse() aus den Unterklassen immer aufzurufen. Das ist aber erstens doof und zweitens habe ich dann das Problem, dass wegen der zwischengeschobenen Klassen das virtual void validate() nicht bis in der unterste Vererbungshierarchie greift, oder? D.h. wenn in Zwischenklasse ein validate() implementiert ist, meckert der Compiler nicht mehr, falls es in D, Unterklasse von Zwischenklasse, nicht implementiert ist. 😞

    Kann man das vielleicht irgendwie hintricksen? Ganz wichtig wäre, dass es in JEDER Klasse einen Zwang geben muss, eine Validierungsmethode zu implementieren. Mit Compilerfehlern, wenn es vergessen wurde.

    Für Rat wäre ich sehr dankbar,

    der Chrischan



  • Ich denke, dass das so, wie du dir das vorstellst nicht funktioniert. Allerdings würde ich es anderst betrachten.

    Für die Member der abgeleiteten Klasse ist ja die Klasse selbst verantwortlich und das kannst du als Programmierer der Basisklasse gar nicht beeinflussen. Also ist es lediglich deine Aufgabe deine Basisklasse konsistent zu halten, was du z.B durch das kapseln der Datenmember machen kannst. Sprich du deklarierst die Datenmember bei dir alle privat und stellst Zugriffsfunktionen bereit, welche dann die Änderungen bewachen können.

    Und nun könntest du von diesen Setter und/oder Getter eine virtuelle Funktion check aufrufen, welche die abgeleitete Klasse definieren muss, was ich allerdings für unnötig befinde, da ja die abgeleitete Klasse selbst über ihre Konsistens verantwortlich ist.



  • OK, dann muss ich mich wohl damit abfinden, dass es anders nicht geht. Ist halt schade, weil es so etwas fehleranfällig wird - man kann beim Ableiten leicht die validate() vergessen zu implementieren und wegen der aus der Basisklasse vorhandenen Implementierung gibt es dann auch keinerlei Hinweis darauf.



  • der_chrischan schrieb:

    OK, dann muss ich mich wohl damit abfinden, dass es anders nicht geht. Ist halt schade, weil es so etwas fehleranfällig wird - man kann beim Ableiten leicht die validate() vergessen zu implementieren und wegen der aus der Basisklasse vorhandenen Implementierung gibt es dann auch keinerlei Hinweis darauf.

    Könnte das ein Fall für einen Unit-Test sein? Falls eine Unterklasse validate() nicht korrekt implementiert, sind die Objekte dieser Klasse "irgendwie" ungültig. Ein Unit-Test müsste das aufdecken, und das wäre der Hinweis, den du brauchst.

    Stefan.



  • Hmm, das wär natürlich ne Idee!
    Nen Unit-Test mit falschen Attributen für jede neu angelegte Unterklasse fordern. Müsste natürlich auch der machen, der die Klasse anlegt, denn es müssen ja speziell neue Attribute getestet werden. Aber ich glaube, fehlende Unit-Tests zu Klassen kann man automatisiert anmeckern lassen. Muss ich mir mal in Ruhe anschauen. Danke für den Tipp.



  • Du darfst in C++ eine Methode durchaus gleichzeitig abstrakt definieren und implementieren.

    class Base
    {
        virtual void validate() = 0;
    };
    
    void Base::validate()
    {
        // Basisimplementierung
    }
    
    class Derived: public Base
    {
        virtual void validate() 
        { 
            Base::validate(); 
            // Neue Implementierung
        }
    };
    

Anmelden zum Antworten