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

时间:2013-03-27 19:45:37

标签: java inheritance override method-overriding

如何使用代码中的Animal实例调用myAnimal类的eat and drink方法?

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

我得到的输出:

Cat Eats
Cat Drinks
Cat Eats
Cat Drinks

这是我的预期输出:

Cat Eats
Cat Drinks
Animal Eats
Animal Drinks

12 个答案:

答案 0 :(得分:61)

你无法做你想做的事。多态性的工作方式是做你所看到的。

基本上猫总是知道它是一只猫并且总是表现得像一只猫,不管你是否像猫,猫,猫科动物,猫科动物,猫科动物,食肉目,Theria,Mammalia,Vertebrata,Chordata,Eumetazoa,Animalia一样对待,动物,物体或其他任何东西: - )

答案 1 :(得分:18)

在这里,您可以选择要调用的方法:

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

答案 2 :(得分:6)

这一行:

Animal myAnimal = myCat;

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

如果要输出Animal Eats,则必须为变量分配Animal实例。所以如果你愿意这样做:

Animal myAnimal = new Animal()

变量myAnimal将是Animal的实例,因此将覆盖之前的Cat赋值。

如果您在此之后拨打myAnimal.eat(),则实际上是在调用您创建的eat()实例的Animal方法,该方法将输出Animal Eats。< / p>

总结:您的代码应为:

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

答案 3 :(得分:2)

如果你在每个类中创建静态方法,它应该可以工作。

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

答案 4 :(得分:2)

您可以为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();
    }
}

答案 5 :(得分:2)

  • 访问静态字段,实例字段和静态方法取决于变量所指向的引用变量类而不是实际对象
  • 请记住,成员变量是阴影的,不会被覆盖。
  • 这与实例方法的情况相反 在实例方法的情况下,调用对象的实际类的方法。

    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对象引用(Animal myAnimal = myCat),但实际对象的类型为Cat,并且它的行为与它是猫一样。

希望这有帮助。

答案 6 :(得分:0)

猫不能不再是猫,即使它是动物。猫会吃,猫会以猫的方式喝。它可能类似于Animal所做的,这就是为什么它会覆盖该方法。如果你想让它做默认动物做的事情,不要覆盖。你可以用反射做一些奇怪的事情,并制作访问父方法的单独方法,如:

public void superDrink() {
   Animal.class.getMethod("drink").invoke();
}

但是你觉得这可能有点矫枉过正?

当然,这可能不会起作用,因为它不是静态的。

答案 7 :(得分:0)

很少有建议:

  1. 不要将子类引用传递给超类,并且必须为重写方法调用超类方法。从超类实例调用超类方法。

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

    public void eat() {
        super.eat();
        System.out.println("Cat Eats");
    }
    
  3. 不要覆盖子类中的超类方法。始终调用超类方法。

答案 8 :(得分:0)

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

输出:

  

Cat eat()叫

     

猫饮()叫

     

动物吃()叫

     

动物饮料()叫

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

答案 9 :(得分:0)

您可以使用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();
 }
}

答案 10 :(得分:0)

您可以对代码进行一些小的更改即可完成您想做的事情。自然地,Animal类的方法已被覆盖,您不能简单地通过更改引用类型来访问它们。取而代之的是,您可以按以下方式稍微更改饮食功能的定义。

class Animal{
    public void eat(boolean randomBoolean){
        System.out.println("Animal eats");
    }
    public void drink(boolean randomBoolean){
        System.out.println("Animal drinks");
    }
}

class Cat extends Animal{
    public void eat(boolean wantOverriden){
        if(wantOverriden){
            boolean randomBooleanValue=true|false;
            super.eat(randomBooleanValue);
        }
        else{
            System.out.println("Cat eats");
        }
    }
    public void drink(boolean wantOverriden){
        if(wantOverriden){
            boolean randomBooleanValue=true|false;
            super.drink(randomBooleanValue);
        }
        else{
            System.out.println("Cat drinks");
        }
    }
}

现在,您应该可以通过简单地传入一个布尔值(表示是否要这样做)来通过Cat类对象访问Animal类的重写方法:

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

答案 11 :(得分:-1)

请不要对这个答案进行投票......你可以对另一个投票:-)这是一个糟糕的答案,但是会说明你将如何做你想做的......很糟糕。

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