2011-04-24 12 views
5

Estoy considerando utilizar una clase abstracta con todos los miembros abstractos en lugar de una interfaz para evitar la implementación explícita de la interfaz código de placa de caldera. Así que en lugar de¿Razones para no usar clase abstracta en lugar de interfaz?

type IMyInterface = 
    abstract Name : string 
    abstract Text : string 

type MyClass() = 
    member __.Name = "name" 
    member __.Text = "text" 
    interface IMyInterface with 
     member this.Name = this.Name 
     member this.Text = this.Text 

Tendría

[<AbstractClass>] 
type MyAbstractClass() = 
    abstract Name : string 
    abstract Text : string 

type MyClass() = 
    inherit MyAbstractClass() 
    override __.Name = "name" 
    override __.Text = "text" 

Cualquier palabra de precaución o implicaciones que debería tener en cuenta aquí?

+4

Si está tomando una decisión entre una interfaz y una clase base abstracta, también podría considerar el uso de ambas. Proporcione un tipo base abstracto del que los implementadores puedan * elegir * heredar y que implemente una interfaz. Luego, acepte referencias a la interfaz, en lugar de a ABC. Esto no funcionará en todos los escenarios (por ejemplo, su código realmente necesita código que está en el ABC para existir en cada implementación concreta, y no puede aceptar una implementación alternativa), pero a menudo puede ser una buena idea. –

+1

@Merlyn Morgan-Graham - ¡Excelente sugerencia! Estoy probando este enfoque y hasta ahora está funcionando muy bien, dando lo mejor de ambos mundos. –

Respuesta

8

Lo único que debe tener en cuenta y tomar una decisión consciente es que una clase puede heredar de una sola clase pero implementar muchas interfaces.


Aparte de eso, algunas recomendaciones sobre el uso de clases abstractas o interfaces:

  • Si prevé la creación de múltiples versiones de su componente, crean una clase abstracta . Las clases abstractas proporcionan una manera simple y fácil de configurar sus componentes con . Al actualizar la clase base, todas las clases heredadas se actualizan automáticamente con el cambio . Las interfaces, por otro lado, no se pueden cambiar una vez creadas. Si se requiere una nueva versión de una interfaz , debe crear una interfaz completamente nueva.
  • Si la funcionalidad que está creando será útil en un amplio rango de objetos dispares , use una interfaz . Las clases abstractas deben ser utilizadas principalmente para objetos que están estrechamente relacionados, mientras que las interfaces son las más adecuadas para proporcionar la funcionalidad común a clases no relacionadas.
  • Si está diseñando pequeñas y concisas funcionalidades, use las interfaces . Si está diseñando unidades funcionales grandes , use una clase abstracta .
  • Si desea proporcionar funcionalidad común implementada entre todas las implementaciones de su componente, use una clase abstracta. Las clases abstractas le permiten implementar parcialmente su clase , mientras que las interfaces no contienen implementación para ningún miembro.

http://msdn.microsoft.com/en-us/library/scsyfw1d%28vs.71%29.aspx

En lo personal, me siento estas recomendaciones son acertadas. Especialmente Las interfaces, por otro lado, no se pueden cambiar una vez creadas. Si se requiere una nueva versión de una interfaz, debe crear una interfaz completamente nueva. es un punto muy importante.

+0

Bien, gracias, ese también me vino a la mente. Definitivamente un biggy. –

+1

No existe un motivo técnico por el que no se pueda cambiar una interfaz, a menos que esté expuesta a través de COM. Los framework/languages ​​de .Net te permiten. En cuanto al control de versiones, se considera una mala práctica realizar cambios bruscos en una interfaz de biblioteca pública, a menos que exista una buena razón, pero la misma recomendación se aplicaría a los tipos de base abstractos, es decir, agregar miembros abstractos adicionales. –

+0

¿Puede explicar lo que quiere decir con "el .NET framework/languages ​​le permiten" – manojlds

4

Esteban,

Sólo uno, el más básico y obvio ... Una interfaz permite implementaciones alternativas; si el "tipo de publicación bien conocido" es una clase abstracta, no puede proporcionar más adelante alternativas ...Entonces, la desventaja es que estás limitando tus opciones futuras; Lo bueno es que (dependiendo de la cantidad de herederos que haya) puede guardar un montón de código de placa de caldera.

Si realmente está realmente seguro de que NO HAY otras implementaciones válidas, vaya a la clase abstracta. Si no, quédate con la interfaz.

Y supongo que PODRÍAS hacer ambas cosas ... y supongo que eso te daría lo mejor de ambos mundos.

Saludos. Keith.

PS: manojlds es cierto, por supuesto ... y tan mucho más sucinct ;-)

+0

Creo que el uso de interfaces limita las opciones futuras más que las clases abstractas. Si envía una interfaz, no puede cambiarla más tarde si sus requisitos cambian, porque cualquier cambio es un cambio radical. Las clases abstractas son mucho más flexibles, ya que puede agregar miembros virtuales y ajustar la implementación interna, siempre que los métodos abstractos públicos no cambien sus firmas. –

+0

Mark, usted tiene un punto "válido", simplemente no es, en mi humilde opinión, uno muy "importante". En mi experiencia, es MUCHO más común necesitar "una variante de una clase existente"; versos "que necesitan agregar un método a una interfaz PUBLICADA existente". Muy simple; una vez que una interfaz alcanza la etapa de publicación, se establece en piedra; de lo contrario, no lo publicaría, ¿verdad? – corlettk

+0

Los requisitos pueden cambiar después de la publicación, más de lo que a nadie le gustaría. Considere la posibilidad de exponer una interfaz de complemento y luego descubrir que la necesita para hacer más de lo que estaba haciendo.La solución cuando se usa una interfaz es que se necesita crear una nueva interfaz, y luego se bloquea la aplicación de múltiples arquitecturas de complementos, donde con una clase abstracta, ese problema no existe, porque las nuevas características se pueden agregar como virtuales. métodos. He tenido este problema varias veces. También he visto esto varias veces en varios proyectos de código abierto. Sin embargo, no puedo pensar en nada fuera de mi cabeza. –

2

En clase abstracta, se puede implementar un comportamiento común de todas las subclases.

En el diseño de su interfaz, es posible que desee tener un método llamado otro método para realizar alguna tarea compuesta. Por ejemplo, predictAll(Instance array) puede usar predictSingle(Instance) y proporciona una implementación predeterminada para todas las subclases. Si usa la interfaz, debe implementar predictAll en todas las subclases.

Pero este punto no es un gran problema como el de herencia múltiple. Prefiero la interfaz más que la clase abstracta.

La interfaz también mantiene su diseño amarillento.

Un punto más: La interfaz alienta más funcional código que la clase abstracta. Typeclass en Haskell es una interfaz más poderosa.

Cuestiones relacionadas