作为面向对象三大知识点之一, 多态可以讲是相对最难理解那个. 本人在这里也是简单分析一下.
一, 多态的定义.
面向对象编程中, 1个超类的引用可以指向属于超类的对象, 也可以根据需要指向超类的派生类族对象.
这个过程中根据引用指向不同类型对象, 可以调用不同方法, 这就是多态.
1.1 什么是类的引用.
Human A;
A = new Human();
new Human() 这个1句是在Heap区动态分配1块Human类型的内存. A = new Human(); 就是把该内存的头部地址赋给A.
1.2 类的引用的指向可以改变
Human A = new Human();
Human B = new Human();
A = B;
再执行上面的语句, 意思就是把A指向了B保存的地址, 也就是说A 和 B 现在是指向同一块内存地址了.
1.3 超类的引用可以指向其子孙派生类的内存地址.
package Object_kng.Ploy_kng;
class Human_1{
private int id;
private int name;
}
class Student_1 extends Human_1{
private String school;
}
class Section_monitor_1 extends Student_1{
private String subject;
}
public class Poly_1{
public static void f(){
Human_1 hm = new Human_1();
Student_1 st = new Student_1();
Section_monitor_1 sm = new Section_monitor_1();
//st = hm; //error
//st = (Student_1)hm; //error (can pass the compilation, but will fail in excution)
//ok
hm = st;
//ok
hm = sm;
//st = hm; //error
st = (Student_1)hm; //ok
}
}
//st = hm; //error
//st = (Student_1)hm; //error (can pass the compilation, but will fail in excution)
[java] java.lang.ClassCastException: Object_kng.Poly_kng.Human_1 cannot be cast to Object_kng.Poly_kng.Student_1
java里不允许把超类对象转成 派生类对象.... 也就是不是任意1个普通人类都能作为学生来看待了.
hm = st;
hm = sm;
//st = hm; //error
st = (Student_1)hm; //ok
这段就稍稍复杂, 首先把 hm 指向它的 孙派生类的对象, 这个也没问题.
st = (Student_1)hm;
1.4 据引用指向不同类型对象, 可以调用不同方法
package Object_kng.Poly_kng;
class Human_2{
public void print(){
System.out.printf("it's Human\n");
}
}
class Student_2 extends Human_2{
public void print(){
System.out.printf("it's Student\n");
}
}
class Section_monitor_2 extends Student_2{
public void print(){
System.out.printf("it's Section_monitor\n");
}
}
public class Poly_2{
public static void f(){
Human_2 hm = new Human_2();
Student_2 st = new Student_2();
Section_monitor_2 sm = new Section_monitor_2();
hm.print();
hm = st;
hm.print();
hm = sm;
hm.print();
}
}
hm.print() 分别执行的是3个不同类的方法:
[java] it's Human
[java] it's Student
[java] it's Section_monitor
二, 多态的一个简单应用.
class Human_3{
private int id;
private String name;
public Human_3(int id,String name){
this.id = id;
this.name = name;
}
public String get_mem(){
return "Human: " + id + " " + name;
}
}
class Student_3 extends Human_3{
public Student_3(int id, String name){
super(id,name);
}
public String get_mem(){
return "student: " + super.get_mem();
}
}
class Section_monitor_3 extends Student_3{
public Section_monitor_3(int id, String name){
super(id,name);
}
public String get_mem(){
return "section_monitor: " + super.get_mem();
}
}
public class Poly_3{
public static String extend_mem(Human_3 hm){
java.util.Date now = new java.util.Date();
java.text.DateFormat d1 = java.text.DateFormat.getDateInstance();
return d1.format(now) + ": " + hm.get_mem();
}
public static void print(){
Human_3 hm = new Human_3(1,"Jack");
Student_3 st = new Student_3(2,"Dick");
Section_monitor_3 sm = new Section_monitor_3(3,"Cindy");
System.out.printf("%s\n",extend_mem(hm));
System.out.printf("%s\n",extend_mem(st));
System.out.printf("%s\n",extend_mem(sm));
}
}
上面一样定义了那个3个类, 而且具有两个成员, 进行了简单的封装...
三, 多态的一些简单要点:
这里也是算是1个简单总结吧:
1. 派生类对象更可以直接赋给父类引用, 但父类对象任何情况下都不能直接赋给超类引用.
2. 如果1个超类引用指向了1个派生类对象, 只能访问派生类对象继承自己超类的成员or方法. 而不能访问派生类独有的成员or方法.
3. 超类引用永远不可能直接赋给派生类引用.
例如用 B extends A. a 是 A的一个引用, b 是B的一个引用
b = a; 肯定是错的.
4. 只有在超类引用本身指向的就是1个派生类或其子孙类(派生类的派生类)对象时, 才可以把超类引用强制转化为派生类引用.
上面的例子, 假如a 指向的实际是B的一个对象.
那么
b = (B)a; 是正确的. 这里必须强制转换.
5. 但是其他情况下不允许把超类引用强制转化为子类引用, 否则会抛出异常, 上面说过了.