2

我有一些关于向上/向下的问题。

我创建了一个抽象超类 Animal、子类 Dog 和子类 BigDog。我还在 Animal 中给出了抽象方法,并在 Dog 和 BigDog 中重写了它。

abstract public class Animal {
    abstract public void greeting();
}

public class Dog extends Animal {
   @Override
   public void greeting() {
      System.out.println("Woof!");
   }
}

public class BigDog extends Dog {
   @Override
   public void greeting() {
      System.out.println("Woow!");
   }
}

现在我的测试代码:

public class TestAnimal {
   public static void main(String[] args) {

      Animal animal2 = new Dog();
      Animal animal3 = new BigDog();

      // Downcast
      Dog dog2 = (Dog) animal2;               //cast Animal class to Dog class, legit
      BigDog bigDog2 = (BigDog) animal3;      //cast Animal to BigDog, legit;
      Dog dog3 = (Dog) animal3;               //Animal Class contains BigDog cast into Dog?
      dog2.greeting();
      dog3.greeting();                    //in which class the method is called?
   }
}

我了解超类/子类之间的关系以及演员表的工作方式。但是,我的问题是,您可以将超类转换为特定的子类,知道两者之间有一个类吗?例如,如果我有一个 Animal 类对象包含一个 BigDog 对象,我可以将该对象强制转换为 Dog 吗?如果 BigDog 中存在 Dog 中不存在的方法怎么办?

简而言之,你当然可以说超类对象是子类对象,但为什么可以反转呢?


转念一想,

我猜这个:我要求 JVM 将 Animal 类引用转换为 Dog 并将新的 Dog 引用链接到 BigDog 对象,而不是真正转换 BigDog 对象。

因此,我可以调用该 Dog 引用(对 BigDog)的所有 Dog 和 Animal 方法,但不能调用 BigDog 方法,除非它在 ​​BigDog 中被覆盖。

Java 在调用方法时检查的是:引用 (DOG) 是否具有引用,以及对象 (BigDog) 是否具有覆盖。如果不是,则调用 Dog 方法,否则调用 BigDog 方法。

谁能证实我的猜测?

4

4 回答 4

2

您始终可以转换为特定的子类,除非编译器足够聪明,可以确定您的转换是不可能的。

转换为子类的最佳方法是检查是否可以完成:

  if ( doggy instanceof BigDog ) {
      doSomethingWithBigdog( (BigDog) doggy );
  } else if ( doggy instanceof SmallDog ) {
      doSomethingWithSmalldog( (SmallDog) doggy );     
  } else {
     // Neither a big dog nor a small dog
  }

  ...

  private void doSomethingWithBigdog( BigDog dog ) {
    ...
  }

  private void doSomethingWithSmalldog( SmallDog dog ) {
    ...
  }

请记住,铸造是邪恶的。有时是必要的,但通常(并非总是)可以通过在基类上实现方法来设计它,或者通过不将 Dog 分配给 Animal 变量而是将其保留为 Dog。

于 2013-08-30T12:02:04.387 回答
0

没有任何方法的签名将与这些方法调用匹配:

dog2.greeting(dog3);
dog3.greeting(dog2); 

所以,它几乎是编译失败。

您需要了解动态方法调度。

这里有几个链接1 , 2 , 3通过它们。

于 2013-08-30T10:10:59.113 回答
0

If I have an Animal class object contains a BigDog object, can I cast the object to Dog? what if there are methods in BigDog that do not exist in Dog?.

简单地你会得到编译器错误。因为你不能调用一个没有在父类中声明并在子类中使用父引用声明的方法

于 2013-08-30T10:13:07.637 回答
0

首先更正源代码,所以它会编译。方法的正确使用:dog2.greeting();dog3.greeting();或添加方法public void greeting(Animal animal);


dog3.greeting();- 调用greeting()方法dog3dog3具有与 相同的参考animal3。对类调用animal3BigDogso方法的引用,输出为greeting()BigDogWoow!


当您Dog从类继承时Animal,类Dog具有类的所有方法Animal

于 2013-08-30T10:26:57.347 回答