Aunque esta es una pregunta general, también es específica de un problema que estoy experimentando actualmente. 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 realizará 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 con NinJect. El problema que tengo es que el área donde necesito usar este IEventContextFactory solo tiene acceso al IContextProvider y usa otra clase que necesitará esta nueva interfaz. No quiero tener que instanciar esta implementación de IEventContextFactory en el nivel bajo y prefiero trabajar con la interfaz IEventContextFactory en todo momento. Sin embargo, tampoco quiero tener que inyectar otro parámetro a través de los constructores solo 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();
}
}
Entonces, mi pregunta principal es, ¿sería esto aceptable o es incluso una práctica común o buena hacer algo como esto (la interfaz se extiende a otra interfaz):
public interface IContextProvider : IEventContextFactory
o debería considerar mejores alternativas para lograr lo que necesito. Si no he proporcionado suficiente información para dar sugerencias, hágamelo saber y puedo proporcionar más.
fuente
Respuestas:
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 a
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 aList
o aSet
. Cada uno de estos hereda todos los requisitos de comportamiento de aCollection
, pero agrega requisitos adicionales específicos para ese tipo particular de colección.Siempre que tenga sentido crear una jerarquía de herencia para las interfaces, entonces debería hacerlo. Si siempre se encuentran dos interfaces juntas, entonces probablemente deberían fusionarse.
fuente
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.
En su ejemplo, no creo que responda sí a ninguno de esos. Puede que sea mejor agregarlo como otra propiedad:
fuente
IContextProvider
extenderIEventContextFactory
, entonces laContextProvider
implementación necesitará implementar ese método también. Si lo agrega como una propiedad, está diciendo que aContextProvider
tiene unIEventContextFactory
pero no conoce los detalles de implementación.Sí, está bien extender una interfaz de otra.
La pregunta de si es lo correcto en un caso específico depende de si existe una verdadera relación "es-a" entre los dos.
¿Qué se requiere para una relación válida "es-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 existe una lógica (razonable) bajo la cual crearía una instancia de la interfaz secundaria que no tendría sentido como una instancia de La interfaz principal.
Si ambos son ciertos, entonces la herencia es la relación correcta para las dos interfaces.
fuente
IReadOnlyList
puede ser útil, incluso si se implementan todas mis clases de listaIList
(que se deriva deIReadOnlyList
).Si una interfaz siempre quiere requerir / proporcionar la otra, entonces adelante. He visto esto en algunos casos con
IDisposible
eso tiene 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, solo haga una interfaz. Si uno siempre necesita al otro, me preocuparía el tipo de herencia "X y 1" que muy a menudo conlleva múltiples responsabilidades y / u otros problemas de abstracción con fugas.
fuente