Mixins mal andersherum



  • Hallo Leute!

    In meiner Recherche über das Thema stieß ich bei 'Mixins' hauptsächlich auf folgende Grundform:

    template< typename Super >
    class Mixin : public Super {
        // Irgendeine zusätzliche Funktionalität
    };
    

    Damit hätte man der Klasse Super also irgendeine Funktionalität hinzugefügt, allerdings "weiß" diese ja nun nichts davon.
    Ich bin nun bei meinen Spielereien schon des öfteren den anderen Weg gegangen:

    template< typename Concrete >
    class MixinInv  // mir fällt gerade kein anderer Name ein
    {
    public:
         void DoSomething() {
              ConcreteCast()->GetSomeHelpFromConcrete();
         }
    
    private:
         Concrete* ConcreteCast() { static_cast< Concrete* >( this ); }
    };
    
    class Some : public MixinInv< Some >
    {
        GetSomeHelpFromConcrete();
    };
    

    , ungefähr nach diesem Schema, sodass die Klasse Some sich über die abgenommene Funktionalität von MixinInv freuen kann, MixinInv sich bei Some melden kann und ich mir die virtuellen Methoden spare, die ansonsten mit einem template method pattern einhergingen, damit sich MixinInv hilfe holen köntne. Gibts dafür einen prägnanten Namen, vielleicht auch einen, der direkt niederschmetternde Kritikpunkte beinhaltet, die ich gerade nicht sehe?^^

    Viele Grüße,
    Deci



  • CRTP = Curiously Recurring Template Pattern

    Probleme sehe ich so allgemein nicht gerade, abgesehen von den üblichen Nachteilen von Templates gegenüber Laufzeitpolymorphie (Festlegung auf Kompilierzeit, alles im Header, Code-Bloat)...

    Ich persönlich verwende auch ab und zu nicht-polymorphe, nicht-templatisierte Basisklassen, die einen Status haben und ein paar entsprechende Methoden anbieten.

    class Positionable
    {
        public:
            Vector GetPosition() const;
            void   SetPosition(Vector v);
            // ...
    
        private:
            Vector mPosition;
    };
    
    class Monster : public Positionable
    {
        // ...
    };
    
    Monster m;
    m.SetPosition(...);
    

    Wie üblich schlechtes Beispiel, aber das Prinzip sollte klar sein. Ach ja, und vielleicht sollte ich erwähnen, dass ich mit dieser Technik in C++ so ziemlich allein zu stehen scheine. Krasse statuslose Interfaces sind halt viel beliebter, auch wenn der Status in jeder abgeleiteten Klasse mit Codeduplizierung neu geschrieben werden muss. 🙂



  • Ja, das mache ich auch ab und zu - ich hab die dann immer namespace concepts (Name, Id, Position, ...). Nur dass man bei den Klassen dann halt fix erlesen kann, welche Zustände die Objekte dann so haben und ich keinen Sinn darin sehe, da extra Interfaces durchzuschleifen. Denke mal, das wird bei dir einen ähnlichen Grund haben.
    Danke für das Nennen des Namens!


Anmelden zum Antworten