Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/394.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何调用超类的重写方法?_Java_Inheritance_Overriding - Fatal编程技术网

Java 如何调用超类的重写方法?

Java 如何调用超类的重写方法?,java,inheritance,overriding,Java,Inheritance,Overriding,如何使用代码中的myAnimal实例调用Animal类的饮食方法 public class Animal { public void eat() { System.out.println("Animal Eats"); } public void drink() { System.out.println("Animal Drinks"); } } 我得到的输出: Cat Eats Cat Drinks Cat Eats Cat

如何使用代码中的
myAnimal
实例调用
Animal
类的饮食方法

public class Animal {
    public void eat() {
        System.out.println("Animal Eats");
    }

    public void drink() {
        System.out.println("Animal Drinks");
    }
}

我得到的输出:

Cat Eats
Cat Drinks
Cat Eats
Cat Drinks
这是我的预期输出:

Cat Eats
Cat Drinks
Animal Eats
Animal Drinks

你不能做你想做的事。多态性的工作方式是做你所看到的事情

基本上,猫总是知道自己是猫,无论你把它当作猫、猫科动物、猫科动物、猫科动物、猫科动物、食肉动物、兽类动物、哺乳类动物、脊椎动物、脊索动物、真动物、动物、物体或其他任何东西,它的行为都会像猫一样:-)

这一行:

Animal myAnimal=myCat

将变量
myAnimal
指定给您以前创建的对象
myCat
。因此,当您在此之后调用
myAnimal.eat()
时,实际上是在调用原始myCat对象的方法,该对象输出
Cat Eats

如果要输出
animaleats
,必须将
Animal
实例分配给变量。因此,如果您要这样做:

Animal myAnimal=new Animal()

变量myAnimal将是
Animal
的一个实例,因此将覆盖先前对
Cat
的赋值

如果在此之后调用
myAnimal.eat()
,实际上是在调用所创建的
Animal
实例的
eat()
方法,该实例将输出
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();
    }
}

请不要对这个答案投票。。。你可以对另一个投票:-)这是一个糟糕的答案,但表明你将如何做你正试图做的事。。。糟糕

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

猫不能停止做一只猫,即使它是一只动物。猫会像猫一样吃喝。它可能与动物的行为相似,这就是为什么它会覆盖该方法。如果你想让它做动物默认做的事情,不要重写。您可能会对反射执行一些奇怪的操作,并创建访问父方法的单独方法,例如:

public void superDrink() {
   Animal.class.getMethod("drink").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");
    }
}

如果您使每个类中的方法都是静态的,那么它应该可以工作

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

您可以为类Animal创建构造函数,该类将另一个Animas作为参数,并基于提供的实例创建新实例

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();
    }
}
  • 对静态字段、实例字段和静态方法的访问取决于参考变量的类,而不是变量指向的实际对象
  • 请记住,成员变量是隐藏的,而不是重写的
  • 这与实例方法的情况相反。
    对于实例方法,调用对象的实际类的方法

    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 myAnimal=myCat
),但实际对象的类型为
Cat
,其行为与猫一样

希望这能有所帮助。

几点建议:

  • 不要将子类引用传递给超类,除非必须为重写的方法调用超类方法。从超类实例调用超类方法

    Animal myAnimal = new Animal();
    myAnimal.eat();
    
  • 若要从子类调用超类方法,请使用super.methodName()显式调用超类方法名称

  • 不要重写子类中的超类方法。始终调用超类方法 输出:

    猫吃东西

    猫喝饮料

    动物吃

    动物饮料


    您需要创建super类
    Animal
    的对象,或者另一个选项是在子类方法中使用关键字
    super
    ,例如
    super.eat()
    super.drink()

    ,您可以使用super关键字实现所需的功能,该关键字允许访问覆盖的方法

    public class Animal {
        public void eat() {
           System.out.println("Animal Eats");
        }
    
        public void drink() {
           System.out.println("Animal Drinks");
        }
    }
    
     public class Cat extends Animal {
    
       public void eat() {
          System.out.println("Cat Eats");
       }
    
       public void drink() {
          System.out.println("Cat Drinks");
       }
    
       public void printMessage(){
         super.eat();
         super.drink();
       }
    
      public static void main(String[] args) {
        Cat myCat = new Cat();
        myCat.eat();
        myCat.drink();
        myCat.printMessage();
     }
    }
    

    您只需对代码进行一些小的更改,就可以做您想做的事情。当然,Animal类的方法已经被重写,您不能简单地通过更改引用类型来访问它们。相反,您可以对eat和drink函数的定义稍作修改,如下所示

    类动物{
    公共void eat(布尔值){
    System.out.println(“动物吃”);
    }
    公共无效饮料(布尔值){
    System.out.println(“动物饮料”);
    }
    }
    猫科动物{
    公共空吃(布尔Wantoveriden){
    如果(Wantoveriden){
    布尔随机布尔值=真|假;
    super.eat(随机布尔值);
    }
    否则{
    System.out.println(“猫吃”);
    }
    }
    公共无效饮料(布尔Wantoveriden){
    如果(Wantoveriden){
    布尔随机布尔值=真|假;
    超级饮料(布尔值);
    }
    否则{
    System.out.println(“猫饮料”);
    }
    }
    }
    
    现在,您应该能够通过Cat类对象访问动物类的重写方法,只需传入一个布尔值,指示是否要这样做,例如:

    Cat c=new Cat();
    c.eat(false);     //Indicating that you dont want to access the overriden method
    c.drink(false);   //Indicating that you dont want to access the overriden method
    c.eat(true);          //Indicating that you want to access the overriden method
    c.drink(true);        //Indicating that you want to access the overriden method
    

    你想调用
    animal
    实现而不调用
    cat
    实现吗?除非你在
    cat
    中有一个witch调用
    super.eat()的方法您不能直接从
    Cat
    执行此操作,您不应该期望您所期望的。。。不应该在语言定义和什么是合理的或可取的方面。继承多态性的全部目的是得到你所看到的,而不是你所说的你所期望的
    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");
        }
    }
    
    public class Animal {
        public void eat() {
           System.out.println("Animal Eats");
        }
    
        public void drink() {
           System.out.println("Animal Drinks");
        }
    }
    
     public class Cat extends Animal {
    
       public void eat() {
          System.out.println("Cat Eats");
       }
    
       public void drink() {
          System.out.println("Cat Drinks");
       }
    
       public void printMessage(){
         super.eat();
         super.drink();
       }
    
      public static void main(String[] args) {
        Cat myCat = new Cat();
        myCat.eat();
        myCat.drink();
        myCat.printMessage();
     }
    }
    
    Cat c=new Cat();
    c.eat(false);     //Indicating that you dont want to access the overriden method
    c.drink(false);   //Indicating that you dont want to access the overriden method
    c.eat(true);          //Indicating that you want to access the overriden method
    c.drink(true);        //Indicating that you want to access the overriden method