How to call the overridden method of a superclass?

95,280

Solution 1

You cannot do what you want. The way polymorphism works is by doing what you are seeing.

Basically a cat always knows it is a cat and will always behave like a cat regardless of if you treat is as a Cat, Felis, Felinae, Felidae, Feliformia, Carnivora, Theria, Mammalia, Vertebrata, Chordata, Eumetazoa, Animalia, Animal, Object, or anything else :-)

Solution 2

Here you will have an option to choose which method do you want to invoke:

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

Solution 3

This line:

Animal myAnimal = myCat;

assigns the variable myAnimal to the object myCat, which you've created before. So when you call myAnimal.eat() after that, you're actually calling the method of the original myCat object, which outputs Cat Eats.

If you want to output Animal Eats, you'll have to assign an Animal instance to a variable. So if you would do this instead:

Animal myAnimal = new Animal()

the variable myAnimal will be an instance of Animal, and thus will overwrite the previous assignment to Cat.

If you will call myAnimal.eat() after this, you're actually calling the eat() method of the Animal instance you've created, which will output Animal Eats.

Concluding: your code should read:

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

Solution 4

  • Access to static fields, instance fields and static methods depends on the class of reference variable and not the actual object to which the variable points to.
  • Remember that member variables are shadowed, not overridden.
  • This is opposite of what happens in the case of instance methods.
    In case of instance methods the method of the actual class of the object is called.

    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
    }
    

In this example although the the object myCat is assigned to an Animal object reference, (Animal myAnimal = myCat) the Actual object is of type Cat and it behaves as it's a cat.

Hope this helps.

Solution 5

You can create constructor for class Animal, that takes another Animas as parameter, and creates new instance based on provided one.

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();
    }
}
Share:
95,280
Hisham Muneer
Author by

Hisham Muneer

Very passionate about programming, computer science and always eager to learn, and happy to teach what I know. From past 7 years I am working closely on Android, Kotlin and Java. Facebook: https://www.fb.com/hisham.dbd Mail me: [email protected] LinkedIn: http://in.linkedin.com/in/hishammuneer/ G+: https://plus.google.com/+HishamMuneer Do you play League of Legends, me too. Here is my tag: "hishamdbd", server EUW. See you on rift.

Updated on July 09, 2022

Comments

  • Hisham Muneer
    Hisham Muneer almost 2 years

    How can I call the eat and drink method of the Animal class with the myAnimal instance in the code?

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

    Output that I am getting:

    Cat Eats
    Cat Drinks
    Cat Eats
    Cat Drinks
    

    This is my expected output:

    Cat Eats
    Cat Drinks
    Animal Eats
    Animal Drinks
    
  • TofuBeer
    TofuBeer about 11 years
    Reflection won't do it either... :-)
  • TofuBeer
    TofuBeer about 11 years
    Reflection (java.lang.reflect) allows you to, among other things, call methods by their name (passed in as a string). However it still won't help since it follows the same rules as what is going on in the code you posted to begin with.
  • Goodwine
    Goodwine about 10 years
    I don't think that's what the OP is asking for, he wants to be able to access the overridden method in an instantiated Object, I would go for something else like redesigning the objects if that is what he is requiring.
  • Ahmed Ghoneim
    Ahmed Ghoneim over 8 years
    java.lang.NoSuchMethodException
  • TofuBeer
    TofuBeer almost 8 years
    @Ced correct, that doesn't compile. The rationale would be that you extended the class for a reason, and that means you have all of the behaviors of the parent.
  • Rob
    Rob about 7 years
    If you admit yourself it's a bad answer and shouldn't be used, it's probably better to just delete it.
  • TofuBeer
    TofuBeer about 7 years
    Not really, it is there to show people what not to do. Anyone can come up with this, I wanted to let people know that if they did then they should throw it away. Hence my request to not vote on it at all...
  • Jim Balter
    Jim Balter about 7 years
    I think it would be better if this were a section of your accepted answer.
  • Yakk - Adam Nevraumont
    Yakk - Adam Nevraumont about 7 years
    This is known as "slicing" in C++; you "slice" the parent part of a Cat to produce an Animal that is no longer a Cat. It happens in C++ using syntax similar ot the OP's syntax. In Java, you have to do it explicitly. Note that this is an improvement, accidental slicing really sucks.
  • Tzen
    Tzen over 4 years
    It will work, but simpler would be to change Animal myAnimal = myCat; to Animal myAnimal = new Animal()
  • truthadjustr
    truthadjustr about 4 years
    I face this interesting scenario today. What I eventually did to work around was to create a private method connectImpl( ) and then I called that method. Otherwise, calling the original connect( ) method routes back to the derive class and results to infinite recursion.
  • jundev
    jundev almost 4 years
    @Vbee, static methods are not overridden but hiding and it will result a compile time error in the case of using @Override annotation above the static method. Prefer to call static methods with className.staticMethodName instead of object reference.