java父类与子类的多态性

[java] view plain copy
 
  1. 父类:  
  2. public class base {  
  3.   
  4.     public String s1 = "base string";  
  5.     public static String s2 = "base static string";   
  6.       
  7.     public void show()  
  8.     {  
  9.         System.out.println(this.s1);  
  10.     }  
  11.       
  12.     public void show_static()  
  13.     {  
  14.         System.out.println(s2);  
  15.     }  
  16.   
  17. }  

子类:

[java] view plain copy
 
  1. public class child extends base {  
  2.       
  3.     public String s1 = "child string";  
  4.     public static String s2 = "child static string";      
  5.       
  6.     public void show()  
  7.     {  
  8.         System.out.println(this.s1);  
  9.     }  
  10.       
  11.     public void show_static()  
  12.     {  
  13.         System.out.println(s2);  
  14.     }  
  15. }  

调用

[java] view plain copy
 
  1. public class mytest {  
  2.   
  3.     public static void main(String[] args)  
  4.     {  
  5.         /* 
  6.         base b1 = new base(); 
  7.         b1.show(); 
  8.      
  9.         child c1 = new child(); 
  10.         c1.show(); */  
  11.           
  12.         base t1 = new child();  
  13.         t1.show();  
  14.         t1.show_static();  
  15.   
  16.         System.out.println(t1.s1);  
  17.         System.out.println(t1.s2);  
  18.     }  
  19.       
  20. }  

结果:

[java] view plain copy
 
  1. child string  
  2. child static string  
  3. base string  
  4. base static string  

结论:

多态支持实例方法,对于实例的字段,实例的静态方法等都是不支持多态。

即:实例方法的引用找的是与实例对应;而静态的内容引用找的是与变量对应。

 

----------------------------------------------------------父类变量调用子类实例的分割线-----------------------------------------------------------------------

通常会在代码里看到用父类的变量来接收子类的实例,然后再调用相应的方法,这样做没有什么特殊的用法,其好处减低代码的耦合度,使代码易于维护。

先看一个例子,

 

[html] view plain copy
 
  1. public class base {  
  2.   
  3.     public String s1 = "base string";  
  4.     public static String s2 = "base static string";   
  5.       
  6.     public void show()  
  7.     {  
  8.         System.out.println(this.s1);  
  9.     }  
  10.       
  11.     public void show_static()  
  12.     {  
  13.         System.out.println(s2);  
  14.     }  
  15. }  
  16.   
  17. public class child extends base {  
  18.       
  19.     public String s1 = "child string";  
  20.     public static String s2 = "child static string";      
  21.       
  22.       
  23.     public void show()  
  24.     {  
  25.         System.out.println(this.s1);  
  26.     }  
  27.       
  28.     public void show_static()  
  29.     {  
  30.         System.out.println(s2);  
  31.     }  
  32. }  
  33.   
  34.   
  35. public class child2 extends base {  
  36.   
  37.     public String s1 = "child2 string";  
  38.     public static String s2 = "child2 static string";     
  39.       
  40.       
  41.     public void show()  
  42.     {  
  43.         System.out.println(this.s1);  
  44.     }  
  45.       
  46.     public void show_static()  
  47.     {  
  48.         System.out.println(s2);  
  49.     }  
  50. }  

调用类:

 

 

[java] view plain copy
 
  1. public class mytest {  
  2.   
  3.       
  4.     public void f1(child cc)  
  5.     {  
  6.         cc.show();  
  7.     }  
  8.       
  9.     public void f2(base bb)  
  10.     {  
  11.         bb.show();  
  12.     }     
  13.       
  14.     public static void main(String[] args)  
  15.     {  
  16.         mytest m1 = new mytest();  
  17.           
  18.         child c1 = new child();  
  19.         m1.f1(c1);  
  20.           
  21.         base b1 = new child();  
  22.         m1.f2(b1);  
  23.           
  24.     }  
  25. }  

上面是有2个方法f1,f2开始干了同样的事情;之后有需求要改变,需要把child类换类child2类;那么对于f1一套的东西来说要改3个地方【申明实例2处和参数申明1处】,而对于f2一套的东西就只改一处地方【实例处】。

 

想想如果参数申明的地方不是一个而是多个,甚至不同类,不同包里,改的地方就多了,还容易漏。所以f1的一套流程就没有f2的一套流程好维护。

修改为child2后的情况见下:

 

[java] view plain copy
 
  1. public class mytest {  
  2.   
  3.     public void f1(child2 cc)  
  4.     {  
  5.         cc.show();  
  6.     }  
  7.       
  8.     public void f2(base bb)  
  9.     {  
  10.         bb.show();  
  11.     }     
  12.       
  13.     public static void main(String[] args)  
  14.     {  
  15.         mytest m1 = new mytest();  
  16.           
  17.         child2 c1 = new child2();  
  18.         m1.f1(c1);  
  19.           
  20.         base b1 = new child2();  
  21.         m1.f2(b1);  
  22.     }  
  23. }  

 

----------------------------------------------------------扩展说明的分割线-----------------------------------------------------------------------

其实严格来说上面的应用还不够严谨,因为虽然父类是同样的,但子类继承父类后自己可以任意扩展的;即有可能child和child2所包含的方法不是完全一致的,这样直接等价替换,f2在调用时就有可能出现找不到方法的异常。所以最好的情况是child和child2继承自同一个接口而不是同一个类,这样就可以避免调用错误的问题了,你想怎么换就怎么换,不用再考虑2个替换类之间的内容差异了,只要新的类能完成新需求即可。

posted @ 2016-12-04 20:59  天涯海角路  阅读(224)  评论(0)    收藏  举报