多态:同一事物(对象),在不同时刻体现的不同状态
举例: 水(固态,液态,气态)
多态的前提:
A:要有继承关系
B*:要有方法重写
C:要有父类或者父接口引用指向子类对象
多态中成员访问特点:
A:成员变量:编译看左边,运行看左边
B:构造方法:创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化,子类的构造都会默认访问父类构造
C:成员方法:编译看左边,运行看右边(因为由于方法重写,运行的时候调用的是子类的成员方法)
D:静态方法:编译看左边,运行看左边
==注意:==在此处由于方法重写,所以运行的时候看右边
代码验证多态中成员访问的特点
A:成员变量:编译看左边,运行看左边
class TestA {
public int num = 10;
public int num2 = 30;
}
class TestB extends TestA {
public int num = 20;
public int num2 = 40;
}
class TestDemo {
public static void main(String[] args) {
TestA a = new TestB();
System.out.println(a.num);//输出结果为:10,
System.out.rintln(a.num2);//输出结果为:30,
}
}
/*
编译运行后的结果为:
10
30
其结果都是父类中的成员变量的值,
再一次验证了:编译看左边,运行看左边
*/
B:构造方法:创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化,子类构造都会默认访问父类构造
class TestA {
public TestA() {
System.out.println("父类TestA");
}
}
class TestB extends TestA {
}
class TestDemo {
public static void main(String[] args) {
//创建子类对象,访问的是父类的构造方法
TestA a = new TestB();//输出结果为:父类TestA
}
}
C:成员方法:编译看左边,运行看右边(因为由于方法重写,运行的时候调用的是子类的成员方法)
class TestA {
public void show() {
System.out.println("父类TestA");
}
}
class TestB extends TestA {
public void show() {
System.out.println("子类TestB");
}
}
class TestDemo {
public static void main(String[] args) {
TestA a = new TestB();
a.show();//调用的是子类的show方法,其实这就是方法重写的调用,
//编译看左边,运行看右边
}
}
/*
编译运行后的结果:
子类TestB
*/
D:静态方法:编译看左边,运行看左边
class TestA {
public static void show() {
System.out.println("父类show");
}
}
class TestB extends TestA {
public static void show() {
System.out.println("子类show");
}
}
class TestDemo {
public static void main(String[] args) {
TeatA a = new TestB();
a.show();//父类show
}
/*
编译运行后的结果为:
父类show
*/
多态的好处
A:提高了代码的维护性(继承保证)
B:提高了代码扩展性(有多态保证)
多态的弊端
A:不能使用子类特有的功能
那么如何使用子类特有的功能?
A:创建子类对象调用即可(方法可行,但是在很多时候不合理。而且,太占内存)
B:把父类的引用强制转换为子类引用(专业名词名词:向下转换)
在此引出对象间的转换问题:
A:向上转换
Fu f = new Zi();
父类引用指向子类对象
B:向下转换
Zi z = (Zi)f; //这里要求f必须是能够转化为Zi的
父类引用转换子类对象
代码举例向下转换
class TestA {
public void show() {
System.out.println("父类show");
}
}
class TestB extends TestA {
public void show() {
System.out.println("子类show");
}
//子类特有
public void function() {
System.out.println("子类特有function");
}
}
class TestDemo {
public static void main(String[] args) {
TestA a = new TestB();
//调用父类和子类共有的方法,会出现方法重新,所调用的但是子类的
a.show();//结果为:子类show
//引用类型转换
//而对于子类特有的方法,就需要将父类引用转换为子类引用
TestB b = (TestA)a;//引用类型转换格式
b.function();//显示结果为:子类特有function
}
}