Question

J'ai l'interface suivante:

internal interface IRelativeTo<T> where T : IObject
{
    T getRelativeTo();
    void setRelativeTo(T relativeTo);
}

et un groupe de classes qui (devraient) l'implémenter, telles que:

public class AdminRateShift : IObject, IRelativeTo<AdminRateShift>
{
    AdminRateShift getRelativeTo();
    void setRelativeTo(AdminRateShift shift);
}

Je me rends compte que ces trois ne sont pas les mêmes:

IRelativeTo<>
IRelativeTo<AdminRateShift>
IRelativeTo<IObject>

mais néanmoins, j'ai besoin d'un moyen de travailler avec toutes les classes différentes comme AdminRateShift (et FXRateShift, DetRateShift) qui devraient toutes implémenter IRelativeTo. Disons que j'ai une fonction qui renvoie AdminRateShift en tant qu'objet:

IRelativeTo<IObject> = getObjectThatImplementsRelativeTo(); // returns Object

En programmant sur l'interface, je peux faire ce dont j'ai besoin, mais je ne peux pas réellement convertir l'objet en IRelativeTo pour pouvoir l'utiliser.

C’est un exemple trivial, mais j’espère que cela clarifiera ce que j’essaie de faire.

Était-ce utile?

La solution

Si je comprends la question, l'approche la plus courante serait de déclarer une interface de base non générique, c'est-à-dire

.
internal interface IRelativeTo
{
    object getRelativeTo(); // or maybe something else non-generic
    void setRelativeTo(object relativeTo);
}
internal interface IRelativeTo<T> : IRelativeTo
    where T : IObject
{
    new T getRelativeTo();
    new void setRelativeTo(T relativeTo);
}

Une autre option consiste à coder en grande partie dans les génériques ... c’est-à-dire que vous avez des méthodes comme

.
void DoSomething<T>() where T : IObject
{
    IRelativeTo<IObject> foo = // etc
}

Si le IRelativeTo<T> est un argument de DoSomething(), généralement vous n'avez pas besoin de spécifier vous-même l'argument de type générique - le compilateur l'inférera - i.e.

DoSomething(foo);

plutôt que

DoSomething<SomeType>(foo);

Les deux approches présentent des avantages.

Autres conseils

Malheureusement, l'héritage ne fonctionne pas avec les génériques. Si votre fonction attend IRelativeTo, vous pouvez également la rendre générique:

void MyFunction<T>(IRelativeTo<T> sth) where T : IObject
{}

Si je me souviens bien, lorsque vous utilisez la fonction ci-dessus, vous n'avez même pas besoin de spécifier le type, le compilateur devrait le déterminer en fonction de l'argument que vous fournissez.

Si vous souhaitez conserver une référence à l'un de ces objets IRelativeTo dans une classe ou une méthode (et vous ne vous souciez pas de ce que T est cela), vous devez redéfinir cette classe / cette méthode / méthode générique.

Je suis d'accord, c'est un peu pénible.

Si tout ce qui vous intéresse, c’est que IRelativeTo traite les IObjects, vous n’avez pas besoin de le rendre générique:

interface IRelativeTo
 {
   IObject getRelativeTo();
   void setRelativeTo(IObject relativeTo)
 }

Les classes d'implémentation peuvent toujours être génériques, cependant:

abstract class RelativeTo<T>  : IRelativeTo where T : IObject
 {  
   public virtual T getRelativeTo() {return default(T);}

   public virtual void setRelativeTo(T relativeTo) {}

   IObject IRelativeTo.getRelativeTo() {return this.getRelativeTo(); }

   void IRelativeTo.setRelativeTo(IObject relativeTo) 
    { this.setRelativeTo((T) relativeTo);
    }
 }

class AdminRateShift :  RelativeTo<AdminRateShift>, IObject {}

Ensuite, vous pouvez faire ceci:

  IRelativeTo irt = new AdminRateShift();
  IObject o = irt.getRelativeTo();
  irt.setRelativeTo(o);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top