Как вызвать переопределенный метод суперкласса

Как я могу вызвать метод eat and drink класса Animal с экземпляром myAnimal в коде?

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();
    }
}

Результат, который я получаю:

Cat Eats
Cat Drinks
Cat Eats
Cat Drinks

Это мой ожидаемый результат:

Cat Eats
Cat Drinks
Animal Eats
Animal Drinks

Ответ 1

Вы не можете делать то, что хотите. Способ полиморфизма работает, делая то, что вы видите.

В основном кошка всегда знает, что это кошка, и всегда будет вести себя как кошка, независимо от того, лечишь ли ты, как кошка, фелис, фелина, фелида, фелефия, карнивора, терия, млекопитающие, вертебрата, хордата, эуметазоа, животные, Animal, Object или что-либо еще: -)

Ответ 2

Здесь у вас будет возможность выбрать, какой метод вы хотите вызвать:

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");
    }
}

Ответ 3

Эта строка:

Animal myAnimal = myCat;

назначает переменную myAnimal объекту myCat, который вы создали ранее. Поэтому, когда вы вызываете myAnimal.eat() после этого, вы на самом деле вызываете метод исходного объекта myCat, который выводит Cat Eats.

Если вы хотите вывести Animal Eats, вам придется назначить экземпляр Animal для переменной. Поэтому, если вы сделаете это вместо этого:

Animal myAnimal = new Animal()

переменная myAnimal будет экземпляром Animal и, таким образом, перезапишет предыдущее назначение Cat.

Если после этого вы вызовете myAnimal.eat(), вы на самом деле вызываете метод eat() созданного экземпляра Animal, который выведет Animal Eats.

Заключение: ваш код должен читать:

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();
    }
}

Ответ 4

Вы можете создать конструктор для класса Animal, который принимает другой параметр Animas as и создает новый экземпляр на основе предоставленного.

public class Animal {
    //some common animal 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 just an Animal.
        Animal myAnimal = new Animal(myCat);         
        myAnimal.eat();
        myAnimal.drink();
    }
}

Ответ 5

  • Доступ к статическим полям, полям экземпляра и статическим методам зависит от класса ссылочной переменной и не фактического объекта, к которому указывает переменная.
  • Помните, что переменные-члены затенены, а не переопределены.
  • Это противоположно тому, что происходит в случае методов экземпляра.
    В случае методов экземпляра вызывается метод фактического класса объекта.

    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(a.x); // 10
      System.out.println(a.y); // 20
      System.out.println(a.getName()); // MNOP
    }
    

В этом примере, хотя объект myCat присваивается ссылке на объект Animal, (Animal myAnimal = myCat), фактический объект имеет тип Cat, и он ведет себя как cat.

Надеюсь, что это поможет.

Ответ 6

Если вы ставите методы в каждом классе static, он должен работать.

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();
    }
}

Приведенный выше код даст следующий вывод

Cat Eats
Cat Drinks
Animal Eats
Animal Drinks

Ответ 7

Кошка не может перестать быть кошкой, даже если это животное. Кошка будет есть, а кошка будет пить на кошачьей дороге. Это может быть похоже на то, что делает Animal, поэтому он переопределяет метод. Если вы хотите, чтобы он делал то, что делает животное по умолчанию, не переопределяйте. Возможно, вы могли бы сделать некоторые странные вещи с отражением и сделать отдельные методы, которые будут обращаться к родительским методам, таким как:

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

но это может быть излишним, разве вы не думаете?

Конечно, это, вероятно, не сработало бы, так как это не статично.

Ответ 8

Несколько предложений:

  • Не передавайте ссылку на класс класса для суперкласса и, кроме того, метод суперкласса должен быть вызван для переопределенного метода. Вызов методов суперкласса из экземпляра суперкласса.

    Animal myAnimal = new Animal();
    myAnimal.eat();
    
  • Если вы хотите вызвать метод супер класса из дочернего класса, явным образом вызовите имя метода суперкласса с помощью метода super.methodName();

    public void eat() {
        super.eat();
        System.out.println("Cat Eats");
    }
    
  • Не переопределяйте метод супер класса в дочернем классе. Вызывается метод супер класса.

Ответ 9

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");
    }
}

ВЫВОД:

Cat eat() называется

cat drink() называется

Животные едят(), называемые

Животный напиток() называется

Вам нужно создать объект суперкласса Animal ИЛИ другой вариант - использовать ключевое слово super в методах дочернего класса, например, super.eat() или super.drink()

Ответ 10

Пожалуйста, не голосуйте за этот ответ... вы можете проголосовать за другого:-) Это плохой ответ, но показывает, как вы будете делать то, что вы пытаетесь сделать... плохо.

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();
    }
}