¿Cómo llamar al método anulado de una superclase?

¿Cómo puedo llamar al método de comer y beber de la clase Animal con la instancia myAnimal en el código?

 public class Animal { public void eat() { System.out.println("Animal Eats"); } public void drink() { System.out.println("Animal Drinks"); } } 

 public class Cat extends Animal { @Override public void eat() { System.out.println("Cat Eats"); } @Override public void drink() { System.out.println("Cat Drinks"); } public static void main(String[] args) { Cat myCat = new Cat(); myCat.eat(); myCat.drink(); Animal myAnimal = myCat; myAnimal.eat(); myAnimal.drink(); } } 

Producto que obtengo:

 Cat Eats Cat Drinks Cat Eats Cat Drinks 

Este es mi resultado esperado:

 Cat Eats Cat Drinks Animal Eats Animal Drinks 

No puedes hacer lo que quieras La forma en que funciona el polymorphism es haciendo lo que estás viendo.

Básicamente un gato siempre sabe que es un gato y siempre se comportará como un gato, independientemente de si se trata de un gato, Felis, Felinae, Felidae, Feliformia, Carnivora, Theria, Mammalia, Vertebrata, Chordata, Eumetazoa, Animalia, Animal, Objeto, o cualquier otra cosa 🙂

Aquí tendrá la opción de elegir el método que desea invocar:

 public class Cat extends Animal { public void superEat() { super.eat(); } public void superDrink() { super.drink(); } @Override public void eat() { System.out.println("Cat Eats"); } @Override public void drink() { System.out.println("Cat Drinks"); } } 

Esta línea:

Animal myAnimal = myCat;

asigna la variable myAnimal al objeto myCat , que has creado antes. Entonces, cuando llame a myAnimal.eat() después de eso, en realidad está llamando al método del objeto myCat original, que emite Cat Eats .

Si quieres emitir Animal Eats , tendrás que asignar una instancia Animal a una variable. Entonces, si hicieras esto en su lugar:

Animal myAnimal = new Animal()

la variable myAnimal será una instancia de Animal , y por lo tanto sobrescribirá la asignación anterior a Cat .

Si llama a myAnimal.eat() después de esto, en realidad está llamando al método eat() de la instancia de Animal que ha creado, que generará Animal Eats .

Concluyendo: su código debería decir:

 public class Cat extends Animal { @Override public void eat() { System.out.println("Cat Eats"); } @Override public void drink() { System.out.println("Cat Drinks"); } public static void main(String[] args) { Cat myCat = new Cat(); myCat.eat(); myCat.drink(); Animal myAnimal = new Animal(); myAnimal.eat(); myAnimal.drink(); } } 
  • El acceso a campos estáticos, campos de instancia y métodos estáticos depende de la clase de variable de referencia y no del objeto real al que apunta la variable.
  • Recuerde que las variables miembro están sombreadas, no anuladas.
  • Esto es lo contrario de lo que sucede en el caso de los métodos de instancia.
    En el caso de los métodos de instancia, se llama al método de la clase real del objeto .

     class ABCD { int x = 10; static int y = 20; public String getName() { return "ABCD"; } } class MNOP extends ABCD { int x = 30; static int y = 40; public String getName() { return "MNOP"; } } public static void main(String[] args) { System.out.println(new MNOP().x + ", " + new MNOP().y); ABCD a = new MNOP(); System.out.println(ax); // 10 System.out.println(ay); // 20 System.out.println(a.getName()); // MNOP } 

En este ejemplo, aunque el objeto myCat se asigna a una referencia de objeto Animal, ( Animal myAnimal = myCat ) el objeto real es de tipo Cat y se comporta como si fuera un gato.

Espero que esto ayude.

Puede crear el constructor para la clase Animal, que toma otro parámetro Animas como, y crea una nueva instancia basada en la proporcionada.

 public class Animal { //some common animal's properties private int weight; private int age; public Animal() { // empty. } public Animal(final Animal otherAnimal) { this.weight = otherAnimal.getWeight(); this.age = otherAnimal.getAge(); } public void eat() { System.out.println("Animal Eats"); } public void drink() { System.out.println("Animal Drinks"); } // setters and getters. } public class Cat extends Animal { @Override public void eat() { System.out.println("Cat Eats"); } @Override public void drink() { System.out.println("Cat Drinks"); } public static void main(String[] args) { Cat myCat = new Cat(); myCat.eat(); myCat.drink(); // note: myAnimal is not a Cat, it's just an Animal. Animal myAnimal = new Animal(myCat); myAnimal.eat(); myAnimal.drink(); } } 

Si haces que los métodos en cada clase sean estáticos, deberían funcionar.

 public class Animal { public static void eat() { System.out.println("Animal Eats"); } public static void drink() { System.out.println("Animal Drinks"); } } public class Cat extends Animal { @Override public static void eat() { System.out.println("Cat Eats"); } @Override public static void drink() { System.out.println("Cat Drinks"); } public static void main(String[] args) { Cat myCat = new Cat(); myCat.eat(); myCat.drink(); Animal myAnimal = myCat; myAnimal.eat(); myAnimal.drink(); } } 

El código anterior dará la siguiente salida

 Cat Eats Cat Drinks Animal Eats Animal Drinks 

Pocas sugerencias

  1. No pase la referencia de la clase infantil a la superclase y, a excepción del método superclase, debe invocarse para el método reemplazado. Llame a los métodos de superclase de la instancia de superclase.

     Animal myAnimal = new Animal(); myAnimal.eat(); 
  2. Si desea llamar al método de superclase de la clase secundaria, llame explícitamente al nombre del método de superclase con super.methodName ();

     public void eat() { super.eat(); System.out.println("Cat Eats"); } 
  3. No anule el método de la clase superior en la clase infantil. Siempre se invoca el método de superclase.
 public class Main { public static void main(String[] args) { Cat myCat = new Cat(); myCat.eat(); myCat.drink(); Animal myAnimal = new Animal(); myAnimal.eat(); myAnimal.drink(); } } public class Animal { public void eat(){ System.out.println("Animal eat() called"); } public void drink(){ System.out.println("Animal drink() called"); } } public class Cat extends Animal { @Override public void eat() { System.out.println("Cat eat() called"); } @Override public void drink() { System.out.println("cat drink() called"); } } 

SALIDA:

Cat eat () llamado

bebida de gato () llamada

Animal eat () llamado

Bebida animal () llamada

Necesita crear un objeto de la super.eat() super.drink() u otra opción es usar la palabra clave super en los métodos de clase infantil, por ejemplo, super.eat() o super.drink()

Cat no puede dejar de ser un gato, incluso si es un animal. El gato comerá y el gato beberá como un gato. Puede ser similar a lo que hace un animal, por lo que anula el método. Si desea que haga lo que hace el animal de forma predeterminada, no lo anule. Probablemente puedas hacer algunas cosas raras con la reflexión y crear métodos separados que accedan a los métodos principales, como:

 public void superDrink() { Animal.class.getMethod("drink").invoke(); } 

pero eso podría ser exagerado, ¿no crees?

Por supuesto que probablemente no funcionaría, ya que no es estático.

Por favor, no votes sobre esta respuesta … puedes votar sobre la otra 🙂 Esta es una mala respuesta, pero muestra cómo harías lo que intentas hacer … mal.

 public class Main { public static void main(final String[] argv) { Child child; Parent parent; child = new Child(); parent = child; child.a(); parent.a(); child.otherA(); parent.otherA(); } } class Parent { public void a() { System.out.println("Parent.a()"); } public void otherA() { // doesn't matter what goes here... really should be abstract } } class Child extends Parent { @Override public void a() { System.out.println("Child.a()"); } @Override public void otherA() { super.a(); } }