¿Cuándo usar la clase o interfaz abstracta?

¿Por qué se crean clases abstractas o de interfaz, o cuándo debemos usar clases abstractas o de interfaz?

La interfaz se usa cuando solo quiere declarar qué métodos y miembros DEBE tener una clase. Cualquiera que implemente la interfaz deberá declarar e implementar los métodos listados por la interfaz.

Si también desea tener una implementación predeterminada, use la clase abstracta. Cualquier clase que extienda la clase abstracta tendrá que implementar solo sus métodos abstractos y miembros, y tendrá una implementación predeterminada de los otros métodos de la clase abstracta, que puede anular o no.

–EDIT – se olvidó de mencionar, Earwicker me recordó

Finalmente, puede implementar tantas interfaces como desee, pero solo extender una clase (ya sea abstracta o no). Tenga esto en cuenta antes de elegir.

La diferencia clave es que puede implement múltiples interfaces en una clase, pero solo extend una única clase abstracta. Esto se debe a que una clase abstracta también puede definir campos que almacenan datos, mientras que una interfaz no puede.

Una clase abstracta es una clase que tiene al menos un método abstracto o también puede hacer que todos sus métodos sean abstractos. Obviamente no puede ser instanciado. Debe heredar de una clase abstracta e implementar los métodos abstractos en la clase heredada (es decir, la clase que amplía la clase abstracta).

Las interfaces no son clases en absoluto (así que no las llame clase de interfaz). Las interfaces definen la firma de métodos sin ninguna implementación. Además, las interfaces no tienen campos de miembros. Si implementa una interfaz en una clase, debe proporcionar implementaciones para todos los métodos proporcionados por la interfaz.

Tiene sentido definir una API generalizada para algunas cosas, que puede tener implementaciones completamente diferentes. Las clases abstractas son más útiles para las clases que hacen principalmente lo mismo, pero tienen algunas diferencias sutiles. Puedes combinar ambos enfoques.

Un buen ejemplo es el marco de colecciones de la biblioteca de clases Java. Usted tiene la Lista de interfaz, que define cómo deben comportarse las Listas. Algunas implementaciones son, por ejemplo, ArrayList y LinkedList. A medida que se comportan de manera similar, las cosas que funcionan igual para ambos se implementan en la clase abstracta AbstactList, ambas heredan esto.

Ver Interface es básicamente un “Contrato”. Cuando define una interfaz, está definiendo un Contrato. Donde se extienden las clases abstractas, se implementan las interfaces.

Consideremos un ejemplo.

 public interface Friend { void hello(); } 

Ahora ha definido un contrato que dice que cualquier clase que quiera implementar Friend necesita proporcionar una definición para el método hello() .

Aquí hay una implementación:

 public class myFriend implements Friend { public void hello() println("Done"); } 

Ahora myFriend ha cumplido el contrato. Ahora la pregunta es: ¿Dónde deberían usarse las interfaces?

Las interfaces lo ayudan a definir un comportamiento que debe implementarse. Digamos que tiene una clase A que define alguna funcionalidad. Desea que las otras clases usen esta funcionalidad de clase solo si definen un comportamiento particular (métodos). Usted aplica esta restricción en términos de interfaz.

SamuelCarrijo parece haber respondido bien a esta pregunta.

Además de Java, algunos marcos requieren una interfaz para trabajar. Estoy pensando en (por ejemplo) proxies dynamics o en algunos marcos de proxys de clientes / servidores. Esto se debe a que utilizan la introspección en el objeto para determinar los métodos implementados por las interfaces implementadas por el objeto. De modo que ocasionalmente tiene que implementar una interfaz para un objeto donde, quizás, normalmente no se molestaría.

Tenga en cuenta que este motivo para las interfaces es específico de Java.

Las clases abstractas se usan cuando se está creando una jerarquía de herencia. Sin embargo, la mayoría de las jerarquías de herencia no deben ser demasiado “profundas” (es decir, demasiados niveles de herencia). Muchos libros de diseño orientados a objetos favorecerán las interfaces sobre la herencia (un libro que leí una vez citó a un desarrollador diciendo que “la herencia es la característica más genial [orientada a objetos] que no implementarás”), ya que permite asignar comportamientos a las clases ” por contrato “, donde el contrato es la interfaz.

Vale la pena señalar la respuesta de samuelcarrijo: si quieres tener una implementación predeterminada de un método, deberías usar una clase abstracta que tenga una implementación concreta del método para darle una implementación predeterminada. Esta implementación predeterminada puede anularse en clases secundarias.

¡Espero que esto ayude!