In java, Can we override a method by passing subcl

2020-02-06 23:58发布

As per the rule, while overriding a method in subclass, parameters cannot be changed and have to be the same as in the super class. What if we pass subclass of parameter while overriding method ? Will it be called as overloading or overriding?

Based on my query I have written some code below.
I was expecting the output as "Dog eats Flesh Food" but to my surprise the output is "Animal eats Flesh Food" Will appreciate if someone can explain how does Animal method gets called when the object assigned is of type Dog ?

    class Food {
        public String toString(){
            return "Normal Food";
        }
    }

    class Flesh extends Food {
        public String toString(){
            return "Flesh Food";
        }
    }

    class Animal {
        public void eat(Food food){
            System.out.println("Animal eats "+ food);
        }
    }

    class Dog extends Animal{

        public void eat(Flesh flesh){
            System.out.println("Dog eats "+ flesh);
        }
    }

    public class MyUtil {

        public static void main(String[] args) {

            Animal animal = new Dog(); 

            Flesh flesh = new Flesh();

            animal.eat(flesh);
        }
    }

5条回答
ら.Afraid
2楼-- · 2020-02-07 00:20

The method eat in Dog does not override the method eat in Animal. This is because the arguments are different (one requires Flesh, the other requires Food).

The eat methods are overloads.

Choosing between overloads takes place at compile time, not runtime. It is not based on the actual class of the object on which the method is invoked, but the compile-time type (how the variable is declared).

animal has compile-time type Animal. We know this because the declaration of the variable animal was Animal animal = .... The fact that it is actually a Dog is irrelevant - it is the version of eat in Animal that must be invoked.

On the other hand, the toString method in Flesh does override the toString method in Food.

When one method overrides another it is the actual class of the object that the method is invoked on that determines which version runs.

In the eat method of Animal, even though the argument has compile-time type Food, if you pass an instance of Flesh to it, it is the toString method in Flesh that will execute.

Therefore you get the message "Animal eats Flesh Food".

查看更多
来,给爷笑一个
3楼-- · 2020-02-07 00:27

When you do this: Animal animal = new Dog(); it's upcasting.

And you do not override the method

public void eat(Flesh flesh){
    System.out.println("Dog eats "+ flesh);
}

so it calls the method eat(Food food) of Animal

查看更多
何必那么认真
4楼-- · 2020-02-07 00:31

You can use the @override annotation to inform the compiler that you are trying to override a method within the superclass.

e.g.

 class Dog extends Animal{

    @Override
    public void eat(Flesh flesh){
        System.out.println("Dog eats "+ flesh);
    }
 }

In your code, now the compiler will generate an error, because this method does not override eat, you need to have the same parameter type.

However, changing the Flesh parameter to Food type will resolve the problem:

class Dog extends Animal{

    @Override
    public void eat(Food food){
        System.out.println("Dog eats "+ food);
    }
}

Now you can do the following:

public class MyUtil {

    public static void main(String[] args) {

        Animal animal = new Dog(); 

        Food food = new Flesh();

        animal.eat(food);
    }
}
查看更多
神经病院院长
5楼-- · 2020-02-07 00:40

In java, Can we override a method by passing subclass of the parameter used in super class method?

NO.

Explanation with example :

Assume we can override a method by passing subclass of the parameter used in super class method.

class A {
    public void print(Oject obj) 
    {
      System.out.println(obj.toString());
     }
}

class B extends A {
    @Override
     public void print(String str) 
     {
        System.out.println(str.toString());
     }
}

class C extends A {
   @Override
   public void print(Integer in) {
      System.out.println(in.toString());
   }
}

class MainTest {
   public static void main(String args[]) 
   {
      Integer in = new Integer(3);
      A a = new B(); // developer by mistake types new B() instead of new C()
      a.print(in);  // compiler will allow this because class A has print method which can take any subclass of Object type(in this case any class because Object is superclass of all classes in java).
    }
}

But think what happens during runtime ?

During runtime, method is called on the actual object to which reference is pointing to. In our case it is pointing to class B. So JVM will look into class B for method execution and it would be a great shock to JVM because class B does not have a overriden method with signature public void print(Integer in) and it will fail at runtime.

The consequence of this is application will crash at runtime rather than compile time.

Overriding rules in Java :

  • Arguments must be the same & return types must be compatible
  • The method can't be less accessible

=============================

In your example what happens is :

During compile time : compiler makes sure that eat method can be called on reference type(which is Aniaml class). Since Animal class has a method public void eat(Food food) which can take any Food type and subclass of Food type as input parameter(polymorphism), compilation passes.

In general, compiler guarantees that particular method is callable for a specific reference type.

During run time : Actual method called is, most specific version of the method for that object type(Dog class).Since JVM is not able to find the overriden method i.e with the same method name and same argument type declared in sub class (Dog class), it checks its superclass(Animal class) and finds the method and executes.

public void eat(Food food) and public void eat(Flesh flesh) are not same from the perspective of overriding methods.

In general, when you call a method on an object reference, you're calling the most specific version of the method for that object type during runtime. But if it doesn't find one it will go up the hierarchy.Worst case Super class will definitely have the method implementation otherwise compilation wont pass.

查看更多
▲ chillily
6楼-- · 2020-02-07 00:41

No, we can not in this case you can check it by adding @Override above the eat method in Dog class so compilation error will appear like this :

@Override
public void eat(Flesh flesh){
   System.out.println("Dog eats "+ flesh);
}

Make sure that in override the parameters should be as parent class in type and order.

查看更多
登录 后发表回答