54

如何用代码中的实例调用Animal类的吃喝方法?myAnimal

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
4

12 回答 12

79

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

基本上,猫总是知道它是一只猫,并且无论您是否将其视为猫,猫科动物,猫科动物,猫科动物,猫形目,食肉动物,Theria,哺乳动物,脊椎动物,脊索动物,Eumetazoa,动物界,动物,对象,或其他任何东西:-)

于 2013-03-27T19:50:54.057 回答
30

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

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");
    }
}
于 2014-04-15T21:06:38.737 回答
9

这一行:

Animal myAnimal = myCat;

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

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

Animal myAnimal = new Animal()

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

如果您myAnimal.eat()在此之后调用,您实际上是在调用您创建eat()的实例的方法,该方法将输出.AnimalAnimal 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();
    }
}
于 2013-03-27T19:51:41.470 回答
4
  • 对静态字段、实例字段和静态方法的访问取决于引用变量的类,而不是 变量指向的实际对象。
  • 请记住,成员变量是隐藏的,而不是覆盖的。
  • 这与实例方法的情况相反。
    在实例方法的情况下,调用对象的实际类的方法 。

    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) Actual 对象属于类型Cat并且它的行为与猫一样。

希望这可以帮助。

于 2015-11-27T04:10:34.263 回答
3

您可以为类 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();
    }
}
于 2014-08-19T06:30:46.413 回答
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
于 2014-05-14T23:40:12.240 回答
2

几点建议:

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

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

    public void eat() {
        super.eat();
        System.out.println("Cat Eats");
    }
    
  3. 不要覆盖子类中的超类方法。总是调用超类方法。
于 2016-09-30T11:35:13.263 回答
1

你可以使用 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();
 }
}
于 2019-11-05T15:03:28.377 回答
0

请不要对这个答案投票......你可以对另一个投票:-) 这是一个糟糕的答案,但显示了你将如何做你想做的事情......糟糕。

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();
    }
}
于 2013-03-27T20:01:21.383 回答
0

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

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

但这可能有点矫枉过正,你不觉得吗?

当然,这可能行不通,因为它不是静态的。

于 2013-03-27T20:04:54.773 回答
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");
    }
}

输出:

猫吃()调用

猫喝()调用

动物吃()调用

动物饮料()调用

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

于 2016-10-26T22:09:56.497 回答
0

您可以通过对代码进行一些小的更改来做您想做的事情。自然,Animal 类的方法已被覆盖,您不能简单地通过更改引用类型来访问它们。相反,你可以稍微改变一下 eat 和 Drink 函数的定义,如下所示。

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
于 2020-09-21T17:11:32.807 回答