父类引用指向子类对象是什么意思

痛定思痛。 2022-05-16 12:45 309阅读 0赞

  在java的多态中,经常会看到父类的引用对象指向子类的对象,一开始很迷茫,因为按照之前所学的知识,父类的引用对象指向自身对象或者子类的引用对象指向自身对象都不难理解,因此为了方便理解,下面举了一个例子:水杯和水壶的比喻。

  1. ![1196131-20170723113247434-1166606947.png][]

  下面的一段代码来实现这个比喻:

复制代码

  1. 1 public class Kettle {
  2. 2 public Kettle(){
  3. 3 System.out.println("水壶容量有2升");
  4. 4 }
  5. 5 }
  6. 6
  7. 7 public class Cup extends Kettle {
  8. 8 public Cup(){
  9. 9 System.out.println("水杯容量为0.5升");
  10. 10 }
  11. 11 }
  12. 12
  13. 13 public class Test {
  14. 14 public static void main(String[] args) {
  15. 15 Kettle k = new Kettle(); //父类的引用对象指向自身:把2升水倒入到水壶中,不会溢出
  16. 16 Cup c = new Cup();//子类的引用对象指向自身:把0.5升的水倒入到水杯中,不会溢出
  17. 17 Kettle k1 = new Cup(); //父类的引用对象指向子类:把0.5升的水倒入到水壶中,不会溢出
  18. 18 Kettle k2 = (Kettle)c; //父类的引用对象指向子类中继承父类的那一部分对象:把水杯中的0.5升水倒入到水壶中,不会溢出
  19. 19 Cup c2 = (Cup)k; //子类的引用对象指向父类对象,报错,不能转换类型:水壶里面的水不能倒入到水杯中,会溢出
  20. 20 Cup c3 = (Cup)k2;//相当于Cup c3 = (Cup)(Kettle)c,子类的引用对象指向子类中继承父类的那一部分对象:把水壶中0.5升的水倒入到水杯中,不会溢出
  21. 21 }
  22. 22 }

复制代码

上面的代码运行结果如下:

复制代码

  1. 1 水壶容量有2
  2. 2 水壶容量有2
  3. 3 水杯容量为0.5
  4. 4 水壶容量有2
  5. 5 水杯容量为0.5
  6. 6 Exception in thread "main" java.lang.ClassCastException: mycom.Kettle cannot be cast to mycom.Cup
  7. 7 at mycom.Test.main(Test.java:9)

复制代码

其中报错的哪一行就是Cup c2 = (Cup)k,由于无法转换类型。

  下面来改写一下代码:方法的引用操作

复制代码

  1. 1 public class Kettle {
  2. 2 public void holeWater(){
  3. 3 System.out.println("水壶有装水的功能");
  4. 4 }
  5. 5 }
  6. 6
  7. 7 public class Cup extends Kettle {
  8. 8 public void holeWater(){
  9. 9 System.out.println("水杯也有装水的功能");
  10. 10 }
  11. 11 public void drinkWater(){
  12. 12 System.out.println("水杯可以拿来喝水的功能");
  13. 13 }
  14. 14 }
  15. 15
  16. 16
  17. 17 public class Test {
  18. 18 public static void main(String[] args) {
  19. 19 Kettle k = new Cup(); //父类的引用对象指向子类
  20. 20 k.holeWater();
  21. 21 k.darinkWater(); //报错
  22. 22 }
  23. 23 }

复制代码

  首先,要实现多态,必须有三个条件:父类引用、子类对象、方法覆盖,在上面的程序中,k调用holeWater方法可以正常编译,因为满足三个条件,而后面的drinkWater方法由于在父类中没有,因此在调用时,会报错,没有满足“方法覆盖”的条件,多态实际上是一种机制,在编译时刻,会生成一张虚拟表,来记录所有覆盖的方法,没有被覆盖的方法是不会记录到这张表的.若一个父类引用调用了没有覆盖的子类方法,那么是不符合该表的,那么编译时刻就会报错. 在执行程序的时候,虚拟机会去这张虚拟表中找覆盖的方法,比如引用中实际上存的是一个子类对象引用,那么就会去找子类中的相应的覆盖的方法来执行。

  综上所述,用父类的引用对象指向子类对象,可以隐藏各个对象不同的细节,专注于共同的属性,这就是面向对象的思想。

发表评论

表情:
评论列表 (有 0 条评论,309人围观)

还没有评论,来说两句吧...

相关阅读