Me he estado preguntando cuál es la diferencia entre ellos. ¿Es solo en esto: la clase abstracta declara qué es un objeto y la interfaz dice qué puede hacer el objeto ? ¿O hay algo más profundo? Gracias.
Si puede tener campos, si puede tener un constructor, si cualquiera de esos métodos puede ser protegido/paquete-privado/privado, si los subtipos pueden heredar de otras clases/interfaces abstractas... eso lo cubre todo.
En Java, no hay clases abstractas puras. Una clase que declara solo métodos abstractos también tiene métodos concretos, porque es una subclase, directa o indirectamente, de la clase Object concreta.
Una interfaz es una mejor opción para definir una API abstracta. Java permite que las clases amplíen como máximo una clase, pero implementen múltiples interfaces.
Del tutorial de Java Clases y métodos abstractos (se agregaron saltos de línea):
Sin embargo, con las clases abstractas, puede declarar campos que no son estáticos y finales, y definir métodos concretos públicos, protegidos y privados.
Con las interfaces, todos los campos son automáticamente públicos, estáticos y finales, y todos los métodos que declara o define (como métodos predeterminados) son públicos.
Además, puede extender solo una clase, ya sea abstracta o no, mientras que puede implementar cualquier cantidad de interfaces.
El tutorial también recomienda casos en los que se desea una clase o interfaz abstracta. Parafraseado, recomienda clases abstractas cuando desea compartir código o campos no estáticos, no finales, o usar calificadores de acceso que no sean públicos. Por lo general, ninguno de estos se aplicará a una clase abstracta pura.
Recomienda interfaces cuando desea especificar una API que puede ser implementada por varias clases no relacionadas, o si desea aprovechar la herencia múltiple de tipos de interfaz.
La declaración "clase abstracta declara qué es un objeto" se refiere a la regla que dice que una clase puede heredar de una clase base si tiene una relación "es un" con la clase base. Entonces, un Sedan puede heredar de Car porque un Sedan "es un" Car . Pero eso es sólo una parte de la historia. Por lo general, definimos clases base abstractas para heredar cuando queremos que la clase base abstracta contenga alguna funcionalidad que restrinja las clases derivadas en lo que pueden hacer, a menudo exponiendo métodos final que no se pueden anular. Por lo tanto, una clase base hipotética de resumen de entrega de correo puede ofrecer un método public final prepareAndSend() que invoca anulaciones abstractas en sí mismo llamados stuffEnvelope() , lickEnvelope() , mailEnvelope() , en ese orden. La clase derivada puede anular esos métodos, pero no tiene poder para cambiar el orden en el que se invocarán porque prepareAndSend() es definitivo. No puede imponer tales restricciones con las interfaces.
Las interfaces, por otro lado, describen "capacidades" o "aspectos" que puede tener un objeto. Un objeto puede tener muchas capacidades diferentes, por lo que puede implementar muchas interfaces.
Tenga en cuenta que puede parecer que la relación "es un" puede aplicarse a las interfaces, pero solo ocurre en ciertos ejemplos artificiales o es una ilusión causada por la sintaxis liberal del idioma inglés; no es generalizable, en muchos casos ni siquiera es fáctico, y por eso no existe una regla que diga que un objeto debe tener una relación "es un" con cada interfaz que implementa.
Entonces, por supuesto, alguien puede hacer una interfaz "ICar", no hay nada de malo en eso, en cuyo caso inevitablemente habrá algo que "es un automóvil", pero lo que es más probable que vea son interfaces como "IDrible", "IInsurable", "ITaxable", "IFuelConsumer", etc., todos los cuales describen características. El hecho de que luego pueda decir "un automóvil está sujeto a impuestos" es una casualidad del idioma inglés; un automóvil en realidad no tiene una relación "es un" con "sujeto a impuestos" porque "sujeto a impuestos" ni siquiera es una cosa. Entonces, a quien se le ocurrió ese "ICar" por lo general solo lo pensó como una conveniencia para combinar todas las características de un automóvil en una interfaz común.