简体   繁体   中英

Having trouble with understanding in method call via inheritance

I have a parent class Animal which is inherited by class Dog


    public class Animal {
        private String color;
        private Boolean hasTail;
        private Integer legs;
    
        public Animal(String color, Boolean hasTail , Integer legs){
            this.color = color;
            this.hasTail = hasTail;
            this.legs = legs;
        }
    
        protected void speak(){
            System.out.println("the animal is speaking");
            sleep();
        }
    
        public void  sleep(){
            System.out.println("The animal is sleeping");
        }
    }

    public class Dog extends Animal {
    
        public Dog(String name) {
            super("Black", true, 12);
            this.name = name;
        }
    
        private String name;
    
        public void bark() {
            System.out.println("bow bow bow");
            super.speak();
        }
    
        public void  sleep(){
            System.out.println("The Dog is sleeping");
        }
    }

and when i do

Dog d = new Dog("tommy");
        d.bark();

the output is

bow bow bow
the animal is speaking
The Dog is sleeping

but i was expecting that the output would be

bow bow bow
the animal is speaking
The animal is sleeping

so anyone can please explain in detail that how this is happening? as Animal class should call the sleep method of it's own class and not of the Dog class that's what i was under the impression of and also how does this know if any class has inherited it?

EDIT1:- if i change the method sleep in Animal class from public to private then I am getting the second output .The object is still type of Dog so why it is now giving the second output?

While calling sleep method from speak , as your object is belongs to Dog class obviously it will call sleep method from Dog class .

If you want to call sleep method of Animal class then simply put super.sleep in Dog's sleep method.

 public void  sleep(){
        super.sleep();
    }

You overrided sleep and not speak.

So, when you create an instance of Dog, it uses the Animal speak method (as it is not redifined in Dog) but uses also the Dog sleep method as it is overwritten.

If you want to reach your goal, you should do :

public class Dog extends Animal {

    public Dog(String name) {
        super("Black", true, 12);
        this.name = name;
    }

    private String name;

    public void bark() {
        System.out.println("bow bow bow");
        super.speak();
    }

    public void  sleep(){
        super.sleep();
        System.out.println("The Dog is sleeping");
    }
}

And then you will have

bow bow bow
the animal is speaking
The animal is sleeping
The Dog is sleeping

Do you understand ?

Calling with super only makes sense when you want to call a parent method when there's also a child method of the same name (ie override of the parent method). Dog has no speak() so the super in super.speak() is redundant. Call speak() by itself and get the same result.

To answer the 2nd part:
Changing a method to private means it's only visible to its own class. The parent sleep() can't now be seen by the child, meaning the child sleep() is now a separate method, not an override.
If you try to call a child-only method (ie not an override) from a parent method, it won't compile. Test by calling bark() from speak() .
Your call to method sleep() in this example binds to the method that makes sense, the private method in Animal.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM