一.Java面向对象编程有三大特性:封装,继承,多态
在了解多态之前我觉得应该先了解一下封装和继承的概念,个人觉得继承和封装都是为了多态服务的,且看我一一道来!
1.封装:将属性private,提供public的方法来访问private属性,这样对数据就设置了访问权限,使得程序更加的安全
实例:
1 package test_1; 2 class Time { 3 private int hour; 4 private int minute; 5 6 public int getHour() { 7 return hour; 8 } 9 public void setHour(int hour) { 10 this.hour = hour; 11 } 12 public int getMinute() { 13 return minute; 14 } 15 public void setMinute(int minute) { 16 this.minute = minute; 17 } 18 }
2.继承:子类继承父类,就是为了重用父类的代码,这样在子类中就可以不写那些重复的代码,使得程序更加的精简
实例:(接着上面的例子来的)
1 class Clock extends Time { 2 3 public static void main(String[] args) { 4 Clock clock = new Clock(); 5 clock.setHour(11); 6 clock.setMinute(11); 7 System.out.println(clock.getHour()+":"+clock.getMinute()); 8 } 9 }//结果:11:11
分析:在Clock这个类中我并没有写属性和方法,但是它有输出能调用Time类中的属性和方法,是因为他继承了Time类,这样就精简了代码
3.多态:相同的方法,不同的对象调用,产生不同的行为(个人一句话总结)
既然现在对多态有了一个概念上的认识,那么我们就必须知道多态的实现条件
二.多态的实现条件:继承,重写,向上转型
继承:在多态中必须有存在继承关系的子类和父类
重写:子类继承了父类,那么就继承了父类中的所有方法,如果在子类中对父类中存在的一部分方法进行了重写编写,那么这个过程就叫重写,在调用这些方法的时候就不会调用父类中的这些方法,而是调用子类中被重写的方法,这样才能产生多态行为
向上转型:一句话:父类引用指向子类对象
1 //假如现在有个父类Father和子类Son 2 //向上转型:父类引用指向子类对象 3 Father f1 = new Son();// f是一个父类的引用,但是它却指向了一个子类Son的对象,这个就叫做向上转型 4 5 //既然说到了向上转型,也简单说一下向下转型,(接着上的例子) 6 //向下转型:把指向子类对象的父类引用赋给子类引用 7 Son s1 = new (SOn)f1; 8 //f1是一个指向子类对象的父类引用,被赋给了一个子类引用,这个叫做向下转型 9 10 Father f2 = new Father(); 11 Son s2 = new (Son)f2//错误,不可以进行向下转型,因为f2是一个指向父类的父类引用
向上转型的缺点:只能访问父类中拥有的方法和属性,对于子类中存在但是父类中存在的方法和属性,是不能调用的,即使重载该方法,若子类重写了父类中的某些方法,在调用该方法的时候,一定是调用的子类中重写的方法,而不是调用父类中被重写的方法
只有满足了上面三个条件,我们才能在同一个继承结构中使用同意的逻辑代码处理不同的对象,从而产生多态行为
三.多态实现的两种方式:
1.继承实现
看一个经典例子,摘自:http://www.cnblogs.com/jack204/archive/2012/10/29/2745150.html
1 public class A { 2 public String show(D obj) { 3 return ("A and D"); 4 } 5 6 public String show(A obj) { 7 return ("A and A"); 8 } 9 10 } 11 12 public class B extends A{ 13 public String show(B obj){ 14 return ("B and B"); 15 } 16 17 public String show(A obj){ 18 return ("B and A"); 19 } 20 } 21 22 public class C extends B{ 23 24 } 25 26 public class D extends B{ 27 28 } 29 30 public class Test { 31 public static void main(String[] args) { 32 A a1 = new A(); 33 A a2 = new B(); 34 B b = new B(); 35 C c = new C(); 36 D d = new D(); 37 38 System.out.println("1--" + a1.show(b)); 39 System.out.println("2--" + a1.show(c)); 40 System.out.println("3--" + a1.show(d)); 41 System.out.println("4--" + a2.show(b)); 42 System.out.println("5--" + a2.show(c)); 43 System.out.println("6--" + a2.show(d)); 44 System.out.println("7--" + b.show(b)); 45 System.out.println("8--" + b.show(c)); 46 System.out.println("9--" + b.show(d)); 47 } 48 } 49 /*运行结果: 50 1--A and A 51 2--A and A 52 3--A and D 53 4--B and A 54 5--B and A 55 6--A and D 56 7--B and B 57 8--B and B 58 9--A and D 59 */
分析:
1.A abd A:a1.show(b),a1是一个父类引用指向父类对象,所以调用的方法都是A类本身的,参数b为B型,又因为B继承了A,所以调用的是A中的show(A obj),所以输出是A and A
2.A and A:a1.show(c),a1是一个父类引用指向父类对象,所以调用的方法都是A类本身的,参数c为C型,但是C继承于B,B继承于A,所以调用的方法仍是show(A obj),所以输出是A and A
3.A and D:a1.show(d),a1是一个父类引用指向父类对象,所以调用的方法都是A类本身的,而d是D型的,所以调用的是show(D obj),所以输出是A and D
4.B and A :a2.show(b),a2是一个父类引用指向子类对象,属于向上转型,不清楚的可以看上面向上转型的定义,又因为属于向上转型,子类中有的但是父类中不存在的方法show(B obj)是不能狗被调用的,子类对父类中show(A obj)进行了重写,所以 a2能用的方法只有show(D obj),show(A obj)(这个方法是B类中的那个),参数b为B型,又因为B继承于A,所以调用的是show(A obj)(这个方法是B类中的那个),所以输出为B and A
5.B and A :a2.show(c),通过上面可以知道a2能调用的方法只有show(D obj),show(A obj)(这个方法是B类中的那个),参数c是C型的,又因为C继承于B,B继承于A,所以输出为B and A
6.A and D:a2.show(d),通过4可以知道a2能调用的方法只有show(D obj),show(A obj)(这个方法是B类中的那个),又因为d是D型,所以a2调用的是show(D obj),所以输出为A and D
7.B and B:b.show(b),b是一个父类指向父类的对象,但是因为B继承了A,所以b能调用的方法有show(D obj)(A中的方法,通过继承得来),show(B obj)(B本身的),show(A obj)(重写的A中的),参数b是b型的,所以调用的是show(B obj),所以输出是B and B
8.B and B: b.show(c),通过7知道b能调用的方法只有三个,参数c为C型,C继承于B,因为b可调用的方法中有有面向B的,所以不会因为c为C型,C继承于B,B又继承于A而去调用show(A obj),而是调用show(B obj),所以输出是B and B
9.A and D,b.show(d),通过7知道b能调用的方法只有三个,参数d为D型,所以调用的是show(D obj)(A中的方法,通过继承得来),所以输出为A and D
2.接口实现
经典例子:摘自http://blog.csdn.net/oguro/article/details/53086720
1 interface Dao{ //接口的方法全部都是非静态的方法。 2 3 public void add(); 4 5 public void delete(); 6 } 7 8 9 10 //接口的实现类 11 class UserDao implements Dao{ 12 13 public void add(){ 14 System.out.println("添加员工成功!!"); 15 } 16 17 public void delete(){ 18 System.out.println("删除员工成功!!"); 19 } 20 21 } 22 23 class Demo3 24 { 25 public static void main(String[] args) 26 { 27 //实现关系下的多态 28 Dao d = new UserDao(); //接口的引用类型变量指向了接口实现类的对象。 29 d.add(); 30 31 32 } 33 }
接口实现多态分析:接口类型的引用变量指向了接口实现类的对象,上面代码中Dao就是接口类型,UserDao就是接口实现类的对象,UserDao实现了Dao这个接口
接口 变量 = new 接口实现类对象
总结:
多态两种实现方法总结:父类的引用类型变量指向了子类对象或者是接口类型的引用变量指向了接口实现类的对象
多态机制遵循的原则总结:当父类对象引用变量引用子类对象的时候,被引用对象的类型而不是引用变量的类型决定了调用哪些方法,但是这个被调用的方法必须是在父类中定义过的,也就是说被子类重写的方法!
不足错误之处,欢迎兄弟们拍砖!!!