java - sirve - ¿Por qué una clase abstracta que implementa una interfaz puede perder la declaración/implementación de uno de los métodos de la interfaz?
interfaces poo (7)
Cuando una clase abstracta implementa una interfaz
En la sección Interfaces, se observó que una clase que implementa una interfaz debe implementar todos los métodos de la interfaz. Sin embargo, es posible definir una clase que no implemente todos los métodos de la interfaz, siempre que la clase se declare como abstracta. Por ejemplo,
abstract class X implements Y {
// implements all but one method of Y
}
class XX extends X {
// implements the remaining method in Y
}
En este caso, la clase X debe ser abstracta porque no implementa completamente Y, pero la clase XX, de hecho, implementa Y.
Referencia: http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html
Algo curioso ocurre en Java cuando se usa una clase abstracta para implementar una interfaz: algunos de los métodos de la interfaz pueden faltar por completo (es decir, no está presente ni una declaración abstracta ni una implementación real), pero el compilador no se queja.
Por ejemplo, dada la interfaz:
public interface IAnything {
void m1();
void m2();
void m3();
}
la siguiente clase abstracta se compila alegremente sin una advertencia o un error:
public abstract class AbstractThing implements IAnything {
public void m1() {}
public void m3() {}
}
¿Puedes explicar porque?
Dada la interfaz:
public interface IAnything {
int i;
void m1();
void m2();
void m3();
}
Así es como realmente lo ve Java:
public interface IAnything {
public static final int i;
public abstract void m1();
public abstract void m2();
public abstract void m3();
}
Así que puedes dejar algunos (o todos) de estos métodos abstract
sin implementar, tal como lo harías en el caso de las clases abstract
extienden otra clase abstract
.
Cuando implement
una interface
, la regla de que todos los métodos de interface
deben implementarse en la class
derivada, se aplica solo a la implementación de class
concreta (es decir, que no es abstract
sí misma).
Si de hecho planea crear una abstract class
partir de él, entonces no hay ninguna regla que diga que debe implement
todos los métodos de interface
(tenga en cuenta que en tal caso es obligatorio declarar la class
derivada como abstract
)
Esta bien. Para entender lo anterior, primero debes entender la naturaleza de las clases abstractas. Son similares a las interfaces en ese sentido. Esto es lo que Oracle dice sobre esto here .
Las clases abstractas son similares a las interfaces. No puede crear instancias de ellos, y pueden contener una combinación de métodos declarados con o sin implementación.
Entonces debes pensar en lo que sucede cuando una interfaz extiende otra interfaz. Por ejemplo ...
//Filename: Sports.java
public interface Sports
{
public void setHomeTeam(String name);
public void setVisitingTeam(String name);
}
//Filename: Football.java
public interface Football extends Sports
{
public void homeTeamScored(int points);
public void visitingTeamScored(int points);
public void endOfQuarter(int quarter);
}
... como puedes ver, esto también compila perfectamente bien. Simplemente porque, al igual que una clase abstracta, una interfaz NO se puede crear instancias. Por lo tanto, no es necesario mencionar explícitamente los métodos de su "padre". Sin embargo, TODAS las firmas de métodos principales DO se convierten implícitamente en parte de la interfaz extendida o la implementación de la clase abstracta. Entonces, una vez que una clase apropiada (una que puede ser instanciada) amplía lo anterior, será necesario asegurar que cada método abstracto sea implementado.
Espero que ayude ... ¡y Allahu ''alam!
Esto se debe a que si una clase es abstracta, entonces, por definición, debe crear subclases para crear una instancia. Las subclases serán requeridas (por el compilador) para implementar cualquier método de interfaz que la clase abstracta omitió.
Siguiendo su código de ejemplo, intente crear una subclase de AbstractThing
sin implementar el método m2
y vea qué errores le proporciona el compilador. Te obligará a implementar este método.
Interfaz significa una clase que no tiene implementación de su método, pero con una declaración justa.
Otra mano, la clase abstracta es una clase que puede tener implementación de algún método junto con algún método con declaración justa, sin implementación.
Cuando implementamos una interfaz para una clase abstracta, significa que la clase abstracta heredó todos los métodos de la interfaz. Como, no es importante implementar todo el método en la clase abstracta, sin embargo, se trata de la clase abstracta (también por herencia), por lo que la clase abstracta puede dejar parte del método en la interfaz sin implementación aquí. Pero, cuando esta clase abstracta será heredada por alguna clase concreta, deberán implementar todos los métodos no implementados allí en la clase abstracta.
Las clases abstractas no son necesarias para implementar los métodos. Entonces, aunque implementa una interfaz, los métodos abstractos de la interfaz pueden permanecer abstractos. Si intenta implementar una interfaz en una clase concreta (es decir, no abstracta) y no implementa los métodos abstractos que el compilador le dirá: implemente los métodos abstractos o declare la clase como abstracta.
Perfectamente bien.
No puede crear instancias de clases abstractas ... pero las clases abstractas se pueden usar para alojar implementaciones comunes para m1 () y m3 ().
Entonces, si la implementación de m2 () es diferente para cada implementación, m1 y m3 no lo son. Podría crear diferentes implementaciones concretas de IAnything con solo la implementación de diferentes m2 y derivarse de AbstractThing, respetando el principio DRY. Validar si la interfaz está completamente implementada para una clase abstracta es inútil.
Actualización : Curiosamente, me parece que C # impone esto como un error de compilación. Se ve obligado a copiar las firmas de método y a agregarles un prefijo ''abstract public'' en la clase base abstracta en este escenario ... (algo nuevo todos los días :)