概述
在继承关系下,一个实例(对象)有多种形态,叫做多态;即一个子类对象既是子类对象,也是父类对象;
子类对象指向父类引用变量
父类名称 | 对象名 | = | new | 子类名称() |
---|---|---|---|---|
父类的引用变量 | 赋值、指向(→) | 子类对象 |
多态特点
不能使用子类特有的成员变量和成员方法!会编译失败(编译看父类)
成员变量
仅父类有该成员变量 | 仅子类有该成员变量 | 子父类都有该成员变量 |
---|---|---|
用父类的 | 编译失败 | 用父类的 |
编译和运行都看左边(父类是否拥有,有就用,没有则会编译失败)
成员方法
仅父类有该成员方法 | 仅子类有该成员方法 | 子父类都有该成员方法 |
---|---|---|
用父类的 | 编译失败 | 用子类的 |
编译看左边,运行看右边(父类是否拥有,没有则编译失败;有的话子类是否重写了,是的话用子类,否则用父类)
public class Fu {
String j="父类独有成员变量";
String k="子父类同名成员变量";
public void father() {
System.out.println("父类独有成员方法");
}
public void f() {
System.out.println("父类重名成员方法");
}
}
public class Zi extends Fu{
String i="子类独有成员变量";
String k="子父类同名成员变量";
public void Son() {
System.out.println("子类独有成员方法");
}
@Override
public void f() {
System.out.println("子类重名成员方法");
}
}
public class Test1 {
public static void main(String[] args) {
Fu a=new Zi();
System.out.println(a.j);//父类独有成员变量
System.out.println(a.k);//子父类同名成员变量
//System.out.println(a.i);//编译失败(子类独有成员变量)
a.father();//父类独有成员方法
//a.Son();//编译失败()
a.f();//子类重名成员方法
}
}
多态应用
1.省去了重载方法的冗余代码
2.提高了代码的扩展性:不需要去明确到底传递哪种子类对象,只要能通过编译,都可以实现子类的扩展性(独有)功能(因为运行看右边子类)。
传参
类型自动转换,声明方法时参数列表写父类,传参时传子类,无需类型转换或者重载方法;
返回
类型自动转换,声明方法时返回值类型写父类,方法体定义和调用时实际返回的是任意子类,都无需类型转换或者重载方法;
public class Hardware{
}
public class Mouse extends Hardware{
public click(){
System.out.println("点击");
}
}
public class Keyboard extends Hardware{
public type(){
System.out.println("打字");
}
}
public class MakeProduct(int code){
Public Hardware MakeProduct(){
Hardware h =new Hardware;
if(code==1){
h =new keyboard;
}else if(code==2){
h =new Mouse;
}
return h;
}
}
public class Test{
public static void main(String[] args){
int code=1;//给出编号确定要制造鼠标还是键盘
Hardware h1 =MakeProduct(code);//无论是鼠标还是键盘,都能用hardware接收
h1.type();//编译可以通过
int code=1;//给出编号确定要制造鼠标还是键盘
Hardware h2 =MakeProduct(code);//无论是鼠标还是键盘,都能用hardware接收
h2.type();//编译可以通过
}
}
转型
解决无法使用子类特有的变量和方法的问题
向上转型
即多态,将子类对象赋值给父类变量(类似自动类型转换);
相当于:
int a=10;
double b =a;//没有问题
向下转型
多态写法下(前提),将父类类型的子类对象,转换回子类类型(类似强制类型转换);
相当于:
int a=10;
double b =(double)a;//int可以看做double的子类,故没有问题
public class Zi extends Fu{
int age=30;
public void z() {
System.out.println("子类特有方法");
}
}
public class Fu {
int age=50;
}
public class Test1 {
public static void main(String[] args) {
Fu a =new Zi();
System.out.println(a.age);//多态写法,只能调到父类,结果50
Zi z = (Zi)a;
System.out.println(z.age);//向下转向,使用子类的变量,结果30
z.z();//向下转型,可以使用子类的独有方法,结果输出“子类特有方法”
}
}
类型转换异常
如:护士、教师都是人的子类
当使用多态写法创建了护士对象后,需要向下转型将该对象转回子类类型时,
可能会出现失误将其转换为错误的其他子类(编译通过,运行时异常 ClassCastException)
解决方式
1.先判断该对象是否属于被转到的类型?
对象 instanceof 教师 (该表达式返回Boolean值)
2.判断语句结合表达式,进行向下对应的强转,执行对象专有的功能
public static void f(人类 对象){
if(对象 instanceof 教师){
教师 对象 = (教师) 对象;
对象.教学方法();
}else if(对象 instanceof 护士){
护士 对象 = (护士) 对象;
对象.打针方法();
}
}