Pregunta

Comencé con una interfaz genérica llamada ILogin. Las interfaces requieren que implemente dos propiedades: ID de usuario y Contraseña. Tengo muchas clases de inicio de sesión que implementan esta interfaz. A medida que mi proyecto crecía y crecía, descubrí que muchas clases repetían el ID de usuario y el código de contraseña. Ahora decido que necesito una clase base de inicio de sesión.

¿Es correcto crear una clase de inicio de sesión base abstracta que implemente la interfaz ILogin y que todas mis clases concretas simplemente hereden de la clase abstracta y se anulen cuando sea necesario? Originalmente estaba pensando que no habría problema con esto. Entonces comencé a pensar que ILogin probablemente no era necesario porque probablemente solo sea implementado por mi clase abstracta.

¿Hay algún beneficio en mantener tanto la clase abstracta como la interfaz?

¡Gracias!

¿Fue útil?

Solución

Definitivamente. Pensemos en un ejemplo concreto.

Digamos que tenemos una clase abstracta Animal . Digamos que hacemos algunas subclases Cat , Dog , Mosquito y Eagle . Podemos implementar sus métodos Eat () , Breathe () , Sleep () de la clase abstracta Animal .

Hasta ahora, todo bien. Ahora, supongamos que queremos tener el método Fly () para las clases Mosquito y Eagle . Dado que estos dos organismos no están realmente bien relacionados (uno es un pájaro, otro es un insecto) no sería fácil encontrar un ancestro común para los dos que podamos tener como una clase abstracta. Esto se implementaría mejor mediante una interfaz IFly .

La interfaz IFly puede tener un método Fly () para ser implementado. Ambas clases Mosquito y Eagle pueden ser subclases de la clase abstracta Animal e implementar la interfaz IFly y poder a Eat () , Breathe () , Sleep () y Fly () sin tener algún tipo de impar relación ancestral entre las dos clases.

Otros consejos

Usualmente codifico contra clases abstractas cuando tiene sentido e implemento (y creo en una asamblea / biblioteca de contratos externos) una interfaz en cada clase (abstracta o no) para poder implementar más fácilmente Windows Communication Foundation o inversión de control cuando sea necesario (que casi siempre es para burlarse). Esto se ha convertido en una segunda naturaleza para mí.

Absolutamente La interfaz es siempre el camino correcto, de esa manera cualquier cosa puede implementarla (incluso algo que ya tiene un padre).

La clase abstracta tiende a hacerlo para que no tenga que volver a implementar algunas piezas de esa funcionalidad. Swing lo usa un poco, tendrán una interfaz y luego una implementación predeterminada para que pueda anular solo uno de los 5 métodos o podría encargarse de agregar oyentes por usted, pero no tiene que usar esa clase base si no quiero.

Si su clase abstracta es la clase solo que alguna vez implementará la interfaz, entonces siempre puede verificar las instancias de la clase abstracta, no necesita la interfaz. Pero si desea ser compatible en el futuro con nuevas clases aún no escritas que no extiendan la clase abstracta pero puedan usar la interfaz, entonces siga usando la interfaz ahora.

Estoy de acuerdo con cfeduke. SIEMPRE empiezo con interfaces y en el pasado he usado clases abstractas que implementan interfaces y proporcionan funcionalidad básica para promover la reutilización de código entre las clases que heredan de la clase abstracta. En general, la burla y el COI dependen de la interfaz, solo por esta razón usaría interfaces en mis diseños.

Si la clase abstracta tiene funcionalidad, es aconsejable mantenerla. Pero si solo contiene métodos abstractos y ningún campo. No veo ninguna utilidad para mantener ambos.

Editar: trabajo en código heredado con muchas clases abstractas. Si alguna vez tengo tiempo, agregaré las interfaces (y posiblemente eliminaré los resúmenes vacíos). Porque trabajar con interfaces mejora enormemente las posibilidades. Y honran su nombre definiendo exactamente la interfaz.

Su interfaz define el contrato que debe cumplirse para que el objeto sea aceptado; su clase abstracta define el contrato que debe cumplirse Y define algunos detalles de implementación específicos.

Piénsalo de esta manera; Si cree que es posible que alguien quiera cumplir ese contrato de una manera diferente a la que la clase abstracta esboza (digamos, con una implementación de tipo de datos de respaldo diferente), entonces debe tener tanto la interfaz como la clase abstracta que implementa eso.

Casi no hay sobrecarga involucrada en tener tanto la clase abstracta como la interfaz; Su riesgo con ese enfoque implica principalmente que un codificador posterior se encuentre con la interfaz, sin darse cuenta de que hay una clase abstracta que implementa la interfaz, y creando una implementación completa desde cero donde no es necesario. Yo diría que esto podría solucionarse especificando en la documentación de su interfaz que hay un " predeterminado " implementación de la interfaz en su clase abstracta; Si bien algunos estándares de codificación pueden desaprobar esa práctica, no veo ningún problema real con ella.

Siempre recomendaría que use interfaces. Las clases abstractas tienen la ventaja de que puede agregar la funcionalidad predeterminada, pero requerir que un usuario use su herencia única es bastante agresivo.

Las bibliotecas de clases de Microsoft favorecen las clases abstractas sobre las interfaces en varios casos porque les permite modificar la clase subyacente. Agregar un método a una clase abstracta rara vez rompe a alguien que hereda de ella. Agregar un método a una interfaz siempre rompe sus implementadores. Sin embargo, esto proporciona una de las mejores razones para usar interfaces: la horrible posibilidad de que Microsoft ya haya usado su única herencia.

Sin embargo, sugeriría que, en su caso particular, desee volver a visitar el patrón de diseño que está utilizando. Parece inusual tener una gran cantidad de "tipo de inicio de sesión" clases.

Creo que un beneficio de mantener la interfaz sería la capacidad de futuras clases para implementar múltiples interfaces, mientras que una clase solo puede heredar de una clase abstracta.

Puede ampliar la funcionalidad de las subclases creando una nueva interfaz con un conjunto diferente de métodos.

Suponiendo que está preguntando específicamente cuándo la interfaz y la clase abstracta tienen firmas idénticas ...

... (Si los miembros de la interfaz son diferentes en alguna forma de los miembros de la clase abstracta, entonces, por supuesto, la respuesta es sí, puede ser necesario para ambos)

... pero suponiendo que los miembros sean idénticos, entonces la única razón por la que puedo pensar en necesitar ambos es que si está codificando en un sistema que no permite la herencia de implementación múltiple, hay dos clases en su sistema que necesitan ser polimórficamente similar, pero debe heredar de diferentes clases base ...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top