黑马程序员技术交流社区

标题: 【西安校区】Java多态的实现过程与实现方法分布解答 [打印本页]

作者: 逆风TO    时间: 2020-4-22 09:50
标题: 【西安校区】Java多态的实现过程与实现方法分布解答
注意一句话:任何子类对象都是父类对象这句话是正确的
(任何子类都可以看作父类)
首先看这个例题的完整代码:
[Java] 纯文本查看 复制代码
package jiCheng_duoTai;

public class DuoTaiLiJieLianXiTi {
  public static void main(String[] args) {
   AAA a1 = new AAA();  
   AAA a2 = new BBB();
   BBB b = new BBB();
   C c = new C();
   D d = new D();
   System.out.println(a1.show(b));
   System.out.println(a1.show(c));
   System.out.println(a1.show(d));


//   System.out.println(a2.show(b));
//   System.out.println(a2.show(c));
//   System.out.println(a2.show(d));


//   System.out.println(b.show(b));
//   System.out.println(b.show(c));
//   System.out.println(b.show(d));

   }
}

//先在本类的方法里面找,若没有再找父类(参数相同),如果还没有找到,就再找本类(参数的父类),如果还没有再去父类找
//1. this.m(o);2. super.m(o);3.this.m(super(o));4. super.m(super(O))

   class AAA{
  public String show(D obj) {
   return ("A and D");
  }
  public String show(AAA obj) {//obj=b;
   return ("A and A");
  }
}
class BBB extends AAA {
  public String show(BBB obj) {
   return ("B and B");
  }
  public String show(AAA obj) {
   return ("B and A");
  }
}
class C extends BBB {
}
class D extends BBB {
}

现在来逐步分解,看每个过程的变化状态

状态一:
[Java] 纯文本查看 复制代码
package jiCheng_duoTai;

public class DuoTaiLiJieLianXiTi {
  public static void main(String[] args) {
   AAA a1 = new AAA();  
   AAA a2 = new BBB();
   BBB b = new BBB();
   C c = new C();
   D d = new D();
   System.out.println(a1.show(b));
   System.out.println(a1.show(c));
   System.out.println(a1.show(d));
         }
}
class AAA{
  public String show(D obj) {
   return ("A and D");
  }
  public String show(AAA obj) {//obj=b;
   return ("A and A");
  }
}
class BBB extends AAA {
  public String show(BBB obj) {
   return ("B and B");
  }
  public String show(AAA obj) {
   return ("B and A");
  }
}
class C extends BBB {
}
class D extends BBB {
}

结果显示:
答案分析:
a1是父类AAA的对象,b是子类BBB的对象,当b传到方法show中,先找有没有与b同参数的show方法,显然是没有的,因为a1这就是一个父类,所以找有没有与父类创建的参数,很显然是有的,所以就调用show(AAA obj)这个方法。
同理,对传来的参数c的时候,也调用show(AAA obj)这个方法。
对于传来的参数d的时候,在本类中就找到了同参的对象,所以就调用show(D obj)这个方法。

状态二:
[Java] 纯文本查看 复制代码
public class DuoTaiLiJieLianXiTi {
  public static void main(String[] args) {
   AAA a1 = new AAA();  
   AAA a2 = new BBB();
   BBB b = new BBB();
   C c = new C();
   D d = new D();
   System.out.println(a2.show(b));
   System.out.println(a2.show(c));
   System.out.println(a2.show(d));
  }
}
class AAA{
  public String show(D obj) {
   return ("A and D");
  }
  public String show(AAA obj) {//obj=b;
   return ("A and A");
  }
}
class BBB extends AAA {
  public String show(BBB obj) {
   return ("B and B");
  }
  public String show(AAA obj) {
   return ("B and A");
  }
}
class C extends BBB {
}
class D extends BBB {
}

结果显示:

答案分析:
注意:a2不是BBB子类对象,a2是AAA父类对象,真正运行的时候,new出来的是一个子类对象。
当传来参数是b的时候,首先在本类(BBB)中找有没有方法名和参数一样的方法,很显然有一个这样的方法show(BBB obj),这种想法是没有问题的,但是BBB子类继承父类AAA,当子类重写父类中的成员方法的时候,必须重写的是父类中存在的方法,子类中独有的方法不能在此情况下编译,因为编译的时候,要保证父类中含有这个方法(多态体现的就是父类中有的方法子类也有的这种方法才能够使用,父类中没有的方法在子类中是不能够使用的,不过可以将a2进行强制类型转换,BBB b = (BBB)a2;再用b.show(b)即可。)所以,因为a2是父类对象,父类中没有show(BBB obj)这个方法,这是BBB类自己的方法,所以a2.show(b)一定不会调用show(BBB obj)这个方法,当把b传来的时候,相当于调用父类中的show(AAA obj)方法,但是这个方法在BBB类中已经被子类所重写了,所以调用 的一定是那个重写的方法,即BBB类中的show(AAA obj)方法。

同理,当传来参数c的时候,也是调用BBB类中的show(AAA obj)方法。因为在子类BBB中没有同参数的方法,所以去父类中寻找,仍没有同参数的方法,所以就调用父类中的show(AAA obj)方法(父类引用指向子类对象)。 因为这个方法被子类BBB所重写,所以调用BBB类中的show(AAA obj)方法。

当传来参数d的时候,先在本类中寻找,发现没有同参数的方法,再去父类中寻找,发现了同参数的方法show(D obj),所以就调用这个方法。

状态三:
[Java] 纯文本查看 复制代码
public class DuoTaiLiJieLianXiTi {
  public static void main(String[] args) {
   AAA a1 = new AAA();  
   AAA a2 = new BBB();
   BBB b = new BBB();
   C c = new C();
   D d = new D();


   System.out.println(b.show(b));
   System.out.println(b.show(c));
   System.out.println(b.show(d));
  }
}
class AAA{
  public String show(D obj) {
   return ("A and D");
  }
  public String show(AAA obj) {//obj=b;
   return ("A and A");
  }
}
class BBB extends AAA {
  public String show(BBB obj) {
   return ("B and B");
  }
  public String show(AAA obj) {
   return ("B and A");
  }
}
class C extends BBB {
}
class D extends BBB {
}


结果显示:

结果分析:
注意:b是BBB类自己的对象
当传来参数b的时候,因为BBB类中存在同参数同方法名的方法show(BBB obj),所以直接就调用该方法。

当传来参数c的时候,首先按照思路,先在本类BBB中寻找是否有同方法名同一个类的参数的方法,显然是没有的,所以再去父类中寻找,在AAA类中寻找是否有同方法名同一个类的参数的方法,显然仍是没有的,所以再返回到本类中(BBB类)找这个参数是这个传来的参数的父类的,很显然,BBB类中的两个方法都是参数c的类的父类(c既是BBB子类的直接子类又是AAA的间接子类),所以都能够使用,那么久按照就近原则,所以就调用BBB类中的show(BBB obj)方法。

当把d作为参数传来的时候先在本类中寻找没找到再去父类中找,找到后就调用该方法即可。

方法总结:
①先在本类中寻找有没有同参数同方法名的方法
②如果没有再去父类中寻找有没有同参数同方法名的方法
③如果没有就再在本类中寻找有没有参数是这个传来的参数的父类的
④如果还没有就再去父类中寻找有没有参数是这个传来的参数的父类的
转自:https://blog.csdn.net/qq_45696288/article/details/105616729







欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2