10 Stimmen

Erweiterung einer Klasse und Beibehaltung der binären Abwärtskompatibilität

Ich versuche, einer bestehenden Bibliothek neue Funktionen hinzuzufügen. Ich müsste neue Daten zu einer Klassenhierarchie hinzufügen, damit die Root-Klasse Zugriffsfunktionen für diese Daten hat. Jeder sollte in der Lage sein, diese Daten zu erhalten, nur Unterklassen könnten sie setzen (d.h. öffentliche Getter und geschützte Setter).

Um die Abwärtskompatibilität aufrechtzuerhalten, weiß ich, dass ich keine der folgenden Aktionen durchführen darf (die Liste enthält nur die für mein Problem relevanten Aktionen):

  • Virtuelle Funktionen hinzufügen oder entfernen
  • Hinzufügen oder Entfernen von Mitgliedsvariablen
  • Typ einer bestehenden Mitgliedsvariable ändern
  • Signatur einer bestehenden Funktion ändern

Ich kann mir zwei Möglichkeiten vorstellen, diese Daten zur Hierarchie hinzuzufügen: Hinzufügen einer neuen Mitgliedsvariable zur Root-Klasse oder Hinzufügen von rein virtuellen Accessor-Funktionen (so dass die Daten in Unterklassen gespeichert werden können). Um die Abwärtskompatibilität zu wahren, kann ich jedoch keine dieser Möglichkeiten nutzen.

Die Bibliothek nutzt ausgiebig pimpl Idiom, aber leider ist die Root-Klasse, die ich ändern muss no diese Redewendung verwenden. Unterklassen hingegen verwenden dieses Idiom.

Die einzige Lösung, die mir jetzt einfällt, ist die Simulation einer Mitgliedsvariable mit einer statischen Hash-Map. Ich könnte also eine statische Hash-Map erstellen, dieses neue Mitglied darin speichern und statische Zugriffsfunktionen für sie implementieren. Etwas wie dieses (in Pseudo-C++):

class NewData {...};

class BaseClass
{
protected:
    static setNewData(BaseClass* instance, NewData* data)
    {
        m_mapNewData[instance] = data;
    }

    static NewData* getNewData(BaseClass* instance)
    {
        return m_mapNewData[instance];
    }
private:
    static HashMap<BaseClass*, NewData*> m_mapNewData;      
};

class DerivedClass : public BaseClass
{
    void doSomething()
    {
        BaseClass::setNewData(this, new NewData());
    }
};

class Outside
{
   void doActions(BaseClass* action)
   {
       NewData* data = BaseClass::getNewData(action);
       ...
   }
};

Diese Lösung könnte zwar funktionieren, aber ich finde sie sehr hässlich (natürlich könnte ich auch nicht-statische Accessor-Funktionen hinzufügen, aber das würde die Hässlichkeit nicht beseitigen).

Gibt es noch andere Lösungen?

Ich danke Ihnen.

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