什么是多态?
相同类型的变量,执行同一方法时呈现出不同的行为特征,这就是多态。
不好理解没关系。往下看。
先记住下面一段话:
java引用变量有两种类型:一个是编译时的类型。一个是运行时的类型,编译时的类型由声明该变量时使用的类型决定,运行时的类型由实际赋给该变量的对象决定。如果编译时类型和运行时类型不一致,就会出现所谓的多态。
不好理解看代码(一定要仔细看,试着自己运行一下):
//新建一个父类BaseClass
public class BaseClass {
public int book=6;
private String bookname="bookname";
public void base(){
System.out.println("父类的base方法");
}
public void test(){
System.out.println("父类的test方法");
}
public BaseClass (){
System.out.println("我是父类的构造函数!");
}
}
//再建个子类
public class SubClass extends BaseClass {
public String book ="子类重新定义了一个BOOK";
@Override
public void test() {
System.out.println("……………………子类重写了test方法……………………");
}
public void sub(){
System.out.println("子类独有的方法");
}
public static void main(String[] args) {
BaseClass bc =new BaseClass();
//打印父类的book 输出6
System.out.println("bc.book="+bc.book+"");
//执行父类的 test 和base方法
bc.test();
bc.base();
SubClass su= new SubClass();
//打印子类的book 输出 子类重新定义了一个BOOK
System.out.println("su.book="+su.book);
//执行子类的 base test sub
// base 继承父类的base
su.base();
// 子类覆盖了父类的test方法
su.test();
//子类独有的 sub 方法
su.sub();
// 虽然此子类重新写了test方法,但是父类的test的方法还时不变的
bc.test();
// 下面编译时类型和运行时类型不一样 多态发生
// 编译时的类型 BaseClass
// 运行时的类型 SubClass
BaseClass pl = new SubClass();
//输出 6 --表名访问的时父类的属性
System.out.println("pl.book="+pl.book);
//下面调用将执行从父类继承的base方法
pl.base();
//下面调用将执行子类(SubClass)的test 方法 这是多态发生
//如果输出的时 子类的test信息 多态发生
pl.test();;
//pl.sub() 先注释掉 不然编译出错 为啥?
//pl.sub();
}
}
运行结果如下
好,开始解答问题:
-
pl.sub 为什么编译不通过?
答:pl.sub 编译的时候会提示如下错误:
可以看出来,报错原因是因为父类(BaseClass)中没有这个方法。
为什么没有这个方法那?因为他的编译时类型时 BaseClass,而BaseClass里面确实没有sub方法, SubClass 是他运行时的类型,两类型不一至。 -
pl.test 为什么执行的时子类SubClass 的方法,而不是 BaseClass 的方法?
答:pl 编译时类型时 BaseClass ,而运行时类型是SubClass ,当调用该引用变量的test方法(BaseClass 类中定义了此方法,子类SubClass 覆盖了父类的该方法),实际执行的是SubClass 类 中覆盖后的test方法,这个就是多态。到此为止是不是恍然大悟了。
-
你有没有想过pl.book为什么输出的是6,而不是子类定义的book的值?
答:与方法不同,对象的属性则不具有多态性。通过引用变量来访问其包含的实例属性时,系统总是试图访问他编译时类所定义的属性,而不是他运行时类所定义的属性。