Question

est ma première question ici:)

Je sais que je ne devrais pas vérifier le type d'objet, mais au lieu d'utiliser dynamic_cast, mais cela ne résoudrait pas mon problème.

Je classe appelée extension et interfaces appelées IExtendable et IInitializable, IUpdatable, ILoadable, IDrawable (les quatre derniers sont basiquement les mêmes). Si l'extension implémente l'interface IExtendable, elle peut se prolonger avec différents objets d'extension.

Le problème est que je veux permettre l'extension qui met en œuvre IExtendable pour étendre uniquement avec l'extension qui implémente les mêmes interfaces que l'extension d'origine.

Vous avez probablement n'unerstand pas ce désordre si je tente de l'expliquer avec le code:

class IExtendable
{
public:
 IExtendable(void);

 void AddExtension(Extension*);
 void RemoveExtensionByID(unsigned int);

 vector<Extension*>* GetExtensionPtr(){return &extensions;};
private:
 vector<Extension*> extensions;
};

class IUpdatable
{
public:
 IUpdatable(void);
 ~IUpdatable(void);

 virtual void Update();
};

class Extension
{
public:
 Extension(void);
 virtual ~Extension(void);

 void Enable(){enabled=true;};
 void Disable(){enabled=false;};

 unsigned int GetIndex(){return ID;};

private:
 bool enabled;
 unsigned int ID;

 static unsigned int _indexID;
};

Maintenant, imaginez le cas que je crée extension comme ceci:

class MyExtension : public Extension, public IExtendable, public IUpdatable, public IDrawable
{
public:
    MyExtension(void);
    virtual ~MyExtension(void);

    virtual void AddExtension(Extension*);
    virtual void Update();
    virtual void Draw();
};

Et je veux permettre à cette classe de s'étendre uniquement avec des extensions qui implémente les mêmes interfaces (ou moins). Par exemple, je veux que ce soit en mesure de prendre l'extension qui met en œuvre IUpdatable; ou les deux IUpdatable et IDrawable; mais par exemple, pas d'extension qui implémente ILoadable. Je veux faire cela parce que quand par exemple Mise à jour () sera appelée sur une extension qui implémente IExtendable et IUpdateable, il sera également appelé ces extensions qui étend cette extension.

Alors, quand je suis d'ajouter une extension à l'extension qui met en œuvre IExtendable et certains des IUpdatable, ILoadable ... Je suis obligé de vérifier si l'extension qui va être ajouter implémente ces interfaces aussi. Ainsi, dans le IExtendable :: addExtension (extension *) je aurais besoin de faire quelque chose comme ceci:

void IExtendable::AddExtension(Extension* pEx)
{
bool ok = true;
// check wheather this extension can take pEx
// do this with every interface
if ((*pEx is IUpdatable) && (*this is_not IUpdatable))
ok = false;

if (ok) this->extensions.push_back(pEx);

}

Mais comment? Toutes les idées ce serait la meilleure solution? Je ne veux pas utiliser dynamic_cast et voir si elle retourne null ... merci

Était-ce utile?

La solution

Vous devriez revoir votre conception. Si vous avez besoin ce comportement, peut-être introduire IUpdateExtendable et IDrawExtendable.

La raison pour laquelle l'approche actuelle est mauvaise est qu'il viole le Liskov principe de substitution . Vous dites en gros « cet objet agit comme un IExtendable, mais il ne vraiment pas, à moins que .... » Si une classe implémente une interface, il devrait vraiment être utilisable via cette interface sans tout conditions. Si ce n'est pas, il est un cauchemar de maintenance en attente de se produire.

Autres conseils

Juste une intuition, mais en fonction de ce que vos extensions font, les pourrait vous aider. Vous pouvez également lire sur le motif décorateur .

Je pourrais fusionner toutes ces interfaces pour une classe, donc je voudrais obtenir quelque chose comme ceci:

class Extension
{
public:
Extension(void);
virtual ~Extension(void);

void AddExtension(Extension* pEx){extensions.push_back(pEx);};

virtual void Initialize()
{
for each (Extension* pEx in extensions) pEx->Initialize();
};

virtual void Load()
{
for each (Extension* pEx in extensions) pEx->Load();
};

virtual void Update()
{
for each (Extension* pEx in extensions) pEx->Update();
};

virtual void Draw()
{
for each (Extension* pEx in extensions) pEx->Draw();
};

private:
vector<Extension*> extensions;
};

Mais cela signifierait que toutes les méthodes seraient appelés à chaque extension ajoutée. Par exemple. méthodes vides dans une extension ajoutée qui ne se charge pas de contenu et ne tire rien seraient appelés.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top