¿Deben las interfaces extenderse (y al hacerlo, heredar los métodos de) otras interfaces?

13

Aunque esta es una pregunta general, también es específica de un problema que actualmente estoy experimentando. Actualmente tengo una interfaz especificada en mi solución llamada

public interface IContextProvider
{
   IDataContext { get; set; }
   IAreaContext { get; set; }
}

Esta interfaz se usa a menudo en todo el programa y, por lo tanto, tengo fácil acceso a los objetos que necesito. Sin embargo, en un nivel bastante bajo de una parte de mi programa necesito acceso a otra clase que usará IAreaContext y realice algunas operaciones fuera de él. Así que he creado otra interfaz de fábrica para hacer esta creación llamada:

public interface IEventContextFactory 
{
   IEventContext CreateEventContext(int eventId);
}

Tengo una clase que implementa IContextProvider y se inyecta usando NinJect. El problema que tengo es que el área en la que necesito usar este IEventContextFactory tiene acceso al IContextProvider y utiliza otra clase que necesitará esta nueva interfaz. No quiero tener que crear una instancia de esta implementación de IEventContextFactory en el nivel bajo y preferiría trabajar con la interfaz IEventContextFactory en todo momento. Sin embargo, tampoco quiero tener que inyectar otro parámetro a través de los constructores para que pase a la clase que lo necesita, es decir,

// example of problem
public class MyClass
{
    public MyClass(IContextProvider context, IEventContextFactory event)
    {
       _context = context;
       _event = event;
    }

    public void DoSomething() 
    {
       // the only place _event is used in the class is to pass it through
       var myClass = new MyChildClass(_event);
       myClass.PerformCalculation();      
    }
}

Por lo tanto, mi pregunta principal es si sería aceptable o incluso es una práctica común o buena hacer algo como esto (la interfaz se extiende a otra una interfaz):

public interface IContextProvider : IEventContextFactory

o debería considerar mejores alternativas para lograr lo que necesito. Si no proporcioné suficiente información para dar sugerencias, avíseme y puedo proporcionar más.

    
pregunta dreza 04.09.2012 - 22:46

4 respuestas

10

Si bien las interfaces describen solo el comportamiento sin ninguna implementación, aún pueden participar en las jerarquías de herencia. Como ejemplo, imagine que tiene, por ejemplo, la idea común de un Collection . Esta interfaz proporcionaría algunas cosas que son comunes a todas las colecciones, como un método para iterar sobre los miembros. Luego, puede pensar en algunas colecciones más específicas de objetos, como List o Set . Cada uno de estos hereda todos los requisitos de comportamiento de un Collection , pero agrega requisitos adicionales específicos para ese tipo particular de colección.

Cada vez que tenga sentido crear una jerarquía de herencia para las interfaces, debería hacerlo. Si siempre se encontrarán dos interfaces juntas, probablemente deberían fusionarse.

    
respondido por el Zoe 04.09.2012 - 23:52
6

Sí, pero solo si tiene sentido. Hágase las siguientes preguntas y si una o más se aplican, entonces es aceptable heredar una interfaz de otra.

  1. ¿Interfaz A extiende lógicamente la interfaz B, por ejemplo, IList agrega funcionalidad a ICollection.
  2. ¿Tiene la interfaz una necesidad de definir el comportamiento ya especificado por otra interfaz, por ejemplo, implementando IDisposable si tiene recursos que deben ser ordenados o IEnumerable si puede repetirse?
  3. ¿Cada implementación de la interfaz A requiere el comportamiento especificado por la interfaz B?

En tu ejemplo, no creo que responda sí a ninguno de esos. Puede que sea mejor agregarlo como otra propiedad:

public interface IContextProvider
{
   IDataContext DataContext { get; set; }
   IAreaContext AreaContext { get; set; }
   IEventContextFactory EventContextFactory { get; set; }
}
    
respondido por el Trevor Pilley 05.09.2012 - 00:10
3

Sí, está bien extender una interfaz desde otra.

La pregunta de si es lo correcto en un caso específico depende de si existe una verdadera relación "is-a" entre los dos.

¿Qué se requiere para una relación válida "is-a"?

Primero, debe haber una diferencia real entre las dos interfaces, es decir, debe haber instancias que implementen la interfaz principal pero no la interfaz secundaria. Si no hay y nunca habrá instancias que no implementen ambas interfaces, entonces las dos interfaces deberían fusionarse.

En segundo lugar, debe darse el caso de que cada instancia de la interfaz secundaria debe ser necesariamente una instancia de la principal: no hay lógica (razonable) según la cual crearía una instancia de la interfaz secundaria que no tendría sentido una instancia de la interfaz padre.

Si ambos son verdaderos, entonces la herencia es la relación correcta para las dos interfaces.

    
respondido por el Theodore Murdock 05.09.2012 - 00:15
1

Si la interfaz siempre quiere requerir / proporcionar la otra, entonces adelante. He visto esto en algunos casos con IDisposible que han tenido sentido. Sin embargo, en general, debe asegurarse de que al menos una de las interfaces se comporte más como un rasgo que como una responsabilidad.

Para su ejemplo, no está claro. Si ambos están siempre juntos, simplemente haga una interfaz. Si uno siempre necesita al otro, me preocuparía el tipo de herencia "X y 1" que a menudo conduce a múltiples responsabilidades y / u otros problemas de abstracción con fugas.

    
respondido por el Telastyn 04.09.2012 - 23:25

Lea otras preguntas en las etiquetas