将子类对象转换为超类

时间:2013-08-30 10:08:04

标签: java class casting subclass superclass

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

我创建了一个抽象超类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向Dog转换一个Animal类引用并将新的Dog引用链接到BigDog对象,而不是真正地转换BigDog对象。

所以我可以在Dog引用(对BigDog)上调用所有Dog和Animal方法,但是没有BigDog方法,除非它在BigDog中被覆盖。

调用方法时Java检查的内容是:如果引用(DOG)具有引用,并且对象(BigDog)具有覆盖。如果没有,则调用Dog方法,否则调用BigDog方法。

任何人都可以证实我的猜测吗?

4 个答案:

答案 0 :(得分: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。

答案 1 :(得分:0)

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

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

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

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

这里有几个链接123通过它们。

答案 2 :(得分: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?

只是你会得到编译器错误。因为你不能调用一个未在父类中声明并在子类中使用父引用声明的方法

答案 3 :(得分:0)

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


dog3.greeting(); - 为greeting()调用方法dog3dog3animal3具有相同的引用。 animal3引用了BigDog,因此方法greeting()被调用到类BigDog,输出为Woow!


当您从班级Dog继承Animal时,班级Dog会收到班级Animal中的所有方法。