Cuando llamo a.displayName("Test")
, se llama al método de helado de clase. displayName(String...s)
método toma en argumentos variables. Salida-
test Icecream
test Faloodeh
test Faloodeh: Faloodeh
test Faloodeh: Faloodeh
Pero cuando cambio el método de displayName(String s)
(He comentado que el artículo en el código), entonces se llama al método de la clase faloodeh. nueva output-
test Faloodeh
test Faloodeh
test Faloodeh: Faloodeh
test Faloodeh: Faloodeh
Yo quería saber por qué ocurre esto.
class Icecream{
public void displayName(String...s){
System.out.println(s[0]+" "+"Icecream");
}
/*public void displayName(String s){
System.out.println(s+" "+"Icecream");
}
*/
public void describe(String s) {
System.out.println(s+" "+"Icecream: Ice cream");
}
}
class Faloodeh extends Icecream {
public void displayName (String s){
System.out.println(s+" "+"Faloodeh ");
}
public void describe (String s) {
System.out.println(s+" "+"Faloodeh: Faloodeh");
}
}
class Test {
public static void main(String arg[]) {
Icecream a=new Faloodeh ();
Faloodeh b=( Faloodeh)a;
a.displayName("test");
b.displayName("test");
a.describe("test");
b.describe("test");
}
}
** ** Editar- Gracias por las respuestas. Por favor, ayúdame con otra duda. He cambiado el código para -
class Icecream{
public void displayName(String s){
System.out.println(s+" "+"Icecream");
}
/*public void displayName(String s){
System.out.println(s+" "+"Icecream");
}
*/
public void describe(String s) {
System.out.println(s+" "+"Icecream: Ice cream");
}
}
class Faloodeh extends Icecream {
public void displayName (String...s){
System.out.println(s+" "+"Faloodeh ");
}
public void describe (String s) {
System.out.println(s+" "+"Faloodeh: Faloodeh");
}
}
class Test {
public static void main(String arg[]) {
Icecream a=new Faloodeh ();
Faloodeh b=( Faloodeh)a;
a.displayName("test");
b.displayName("test");
a.describe("test");
b.describe("test");
}
}
Ahora bien, esto da la siguiente output-
test Icecream
test Icecream
test Faloodeh: Faloodeh
test Faloodeh: Faloodeh
Como todos ustedes explicado, aquí b es un objeto de la clase faloodeh. Y displayName(String...s)
de la clase faloodeh no consigue anulación. Todavía en la salida, se muestra test Icecream
¿Por qué?
El punto clave aquí es que el cambio displayName(String... s)
de displayName(String s)
las causas del displayName(String s)
método en el Faloodeh
que anula el método de su superclase.
Icecream.displayName(String... s)
y Faloodeh.displayName(String s)
tener diferentes firmas, para que no se anulan entre sí. Pero el cambio de la primera a aceptar un String
solo les hace tener la misma firma, que causa primordial que se produzca.
En Java, las llamadas a métodos se resuelven en aproximadamente tres pasos (para más información: JLS §15.12 , también he explicado con más detalle aquí ):
- Encuentra la clase a buscar métodos aplicables. Esto se basa en el tipo de tiempo de compilación del objeto sobre el que está llamando el método. En este caso,
a
.a
's compilación tipo de tiempo esIcecream
, por lo que sóloIcecream
' se considerarán s métodos. Tenga en cuenta que no encuentra eldisplayName
métodoFaloodeh
porque el tipo de tiempo de compilacióna
esIcecream
. - Determinar qué sobrecarga del método a llamar sobre la base de los argumentos que ha pasado. Sólo hay una opción aquí. Como antes y después del cambio,
displayName
es la única sobrecarga que es compatible con los argumentos que ha pasado. - Determinar qué aplicación del método a la llamada en función del tipo de tiempo de ejecución del objeto sobre el que llamó al método.
a
's Tipo de tiempo de ejecución esFaloodeh
. Antes del cambio,displayName
no se reemplaza enFaloodeh
, por lo que llama a la implementación de la superclase. Después del cambio,displayName
se convierte anulado, por lo que la aplicación deFaloodeh
que se llama.
Con respecto a su edición:
En este caso, ya que el tipo de tiempo de compilación de b
es Faloodeh
, la clase a buscar es Faloodeh
(Paso 1). Sin embargo, hay 2 métodos que coincide con los argumentos que dio (paso 2):
displayName(String...)
que se declara enFaloodeh
, y;displayName(String)
que se hereda.
En una situación de este tipo, el compilador siempre favorece la sobrecarga sin aridad variables - displayName(String)
. Esto se especifica claramente en JLS §15.12.2 . En particular, la etapa 2 es dividen además en tres más sub-pasos. Los primeros intentos sub-paso para encontrar un método sin permitir métodos Arity variables, y si cualquier sub-paso encuentra cualquier método, se omiten los sub-pasos restantes.