Pregunta

Tengo la siguiente interfaz:

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

y un montón de clases que (deberían) implementarlo, como:

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

Me doy cuenta de que estos tres no son lo mismo:

IRelativeTo<>
IRelativeTo<AdminRateShift>
IRelativeTo<IObject>

pero, no obstante, necesito una forma de trabajar con todas las diferentes clases como AdminRateShift (y FXRateShift, DetRateShift) que deberían implementar IRelativeTo. Digamos que tengo una función que devuelve AdminRateShift como un objeto:

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

Al programar contra la interfaz, puedo hacer lo que necesito, pero en realidad no puedo enviar el Objeto a IRelativeTo para poder usarlo.

Es un ejemplo trivial, pero espero que aclare lo que estoy tratando de hacer.

¿Fue útil?

Solución

Si entiendo la pregunta, entonces el enfoque más común sería declarar una interfaz base no genérica, es decir,

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);
}

Otra opción es que usted codifique en gran medida en genéricos ... es decir, tiene métodos como

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

Si IRelativeTo<T> es un argumento para DoSomething(), entonces generalmente no necesita especificar el argumento de tipo genérico usted mismo; el compilador lo deducirá, es decir,

DoSomething(foo);

en lugar de

DoSomething<SomeType>(foo);

Hay beneficios para ambos enfoques.

Otros consejos

desafortunadamente la herencia no funciona con genéricos. Si su función espera IRelativeTo, también puede hacer que la función sea genérica:

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

Si no recuerdo mal, cuando usa la función anterior, ni siquiera necesita especificar el tipo, el compilador debe resolverlo en función del argumento que proporcione.

Si desea mantener una referencia a uno de estos objetos IRelativeTo dentro de una clase o método (y no le importa qué T es eso), debe hacer que esta clase / método sea genérico nuevamente.

Estoy de acuerdo, es un poco de dolor.

Si todo lo que le importa es que IRelativeTo trata con IObjects, entonces no necesita hacerlo genérico:

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

Las clases de implementación aún pueden ser genéricas, sin embargo:

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 {}

Entonces puedes hacer esto:

  IRelativeTo irt = new AdminRateShift();
  IObject o = irt.getRelativeTo();
  irt.setRelativeTo(o);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top