在java中,我们可以通过传递超类方法中使用的参数的子类来覆盖方法吗?

2022-09-03 12:53:24

根据规则,在重写子类中的方法时,参数不能更改,并且必须与超类中的参数相同。如果我们在重写方法时传递参数的子类怎么办?它会被称为重载还是覆盖?

根据我的查询,我在下面写了一些代码。
我期待输出为“狗吃肉食”,但令我惊讶的是,输出是“动物吃肉食”如果有人可以解释当分配的对象类型为狗时,动物方法如何被调用,将不胜感激?

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

答案 1

中的方法不会覆盖 中的方法。这是因为参数不同(一个需要,另一个需要)。eatDogeatAnimalFleshFood

这些方法是重载。eat

在重载之间进行选择是在编译时进行的,而不是在运行时进行的。它不是基于调用方法的对象的实际类,而是基于编译时类型(变量的声明方式)。

animal具有编译时类型 。我们知道这一点,因为变量的声明是 。它实际上是一个事实是无关紧要的 - 它是必须调用的版本。AnimalanimalAnimal animal = ...DogeatAnimal

另一方面,中的方法覆盖 中的方法。toStringFleshtoStringFood

当一个方法重写另一个方法时,调用该方法的对象的实际类将确定运行哪个版本。

在 的方法中,即使参数具有编译时类型,如果将 的实例传递给它,它就是将执行的方法。eatAnimalFoodFleshtoStringFlesh

因此,您会收到消息 。"Animal eats Flesh Food"


答案 2

不,在这种情况下,我们不能通过在Dog类中的eat方法上方添加@Override来检查它,因此编译错误将如下所示:

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

确保在 override 中,参数应按类型和顺序作为父类。