多态
什么是多态?
多态就是同一个东西,在不同情况下表现出不同的状态。
JAVA为什么要使用多态呢?
因为在现实生活中很多东西,都是在不同的情况下表现出不同的状态。
比如说同一台柜员机,你拿着银行卡去还款或者去取款。
注意:如果你拿的这个信用卡,是本行的银行卡的话,你是既能还款又能取款,而且还能查询余额,可是同一台柜员机,如果你拿着的是其它银行银行卡的话,那对不起就只能取款,这就是一台柜员机,在不同的情况下表现出不同的状态。
概述
多态是指一个对象有多种形态
好处:提高了程序的灵活性.体现程序的通用性.做出统一调用标准
通用性:多态中,不关心具体子类的类型,屏蔽了子类间的不同,会把子类当父类来看
特点
前提: 发生继承关系 + 发生方法重写现象
口诀1: 父类引用 指向 子类对象
Animal a = new Dog();口诀2: 编译看左边,运行看右边
想要保存成功,只能使用 左边 父类的
结果以右边 子类 为准
多态的意义
JAVA多态表现在两个方面:
第一个方面:
一个父类型的变量,如果它引用的子类型对象不同,那么它在运行时执行的方法实现,就是可以不同的。
今后只要在运行时判断执行的是哪个子类中的方法,就看new的是哪个类型的对象,跟等号左边的变量,没有半毛钱关系。
入门案例
package cn.tedu.oop;
//测试 多态
public class Test2_Mulity {
public static void main(String[] args) {
//2, 创建多态对象 -- 口诀1: 父类引用 指向 子类对象
Animal a = new Dog() ;
//3, 使用多态对象 -- 口诀2: 编译看左边, 运行看右边
//多态的目的是统一调用标准,,,标准就是父类 !!
a.eat();//方法声明用了父类的, 方法体用了子类的
//4, 父类中没有,是子类的特有的方法,非得用--多态对象不支持,只能创建子类对象使用
//a.show();
}
}
//1, 前提: 发生继承关系 + 发生方法重写现象
class Animal{
public void eat() {
System.out.println("吃啥都行");
}
}
class Dog extends Animal{
public void show() {
System.out.println("吃啥都行");
}
@Override
public void eat() {
System.out.println("狗吃肉");
}
}
多态的使用
代码
package cn.tedu.oop;
//测试 多态的使用
public class Test3_Mulity {
public static void main(String[] args) {
//创建多态对象测试--口诀1:父类引用 指向 子类对象
Animal2 a = new Dog2();
//使用多态对象--口诀2: 编译看左边,运行看右边
a.eat();//1, 成员方法被重写了,所以用了子类的方法体 和 父类的方法声明
System.out.println( a.name );//2, 成员变量用 父类的
a.show();//3, 静态资源用 父类的
Animal2.show();//show()是父类的
}
}
//前提:继承+重写
class Animal2{
String name = "小动物" ;
public void eat() {
System.out.println("吃肉");
}
static public void show() {
System.out.println("fu..show..");
}
}
class Dog2 extends Animal2 {
String name = "大黄" ;
@Override
public void eat() {
System.out.println("狗吃肉");
}
//4, 静态资源可以被重写吗???--不能 !!!
static public void show() {
System.out.println("zi..show..");
}
}
第二个方面:
第二方面是反过来的,如果一个子类型的对象,“向上造型”为不同的父类型的变量的时候,可用的功能也不是一样的。
什么是向上造型?
向上造型就是子类类型的变量,可以自动“向, 上”转化为父类型的变量
例如:
ATMCBC cbc= new ATMCBC(); //cbc是子类型ATMCBC的变量
//父类型IUnionPay的变量atm可以指向子类型cbc引用的对象。
IUnionPay atm=cbc; //也叫变量cbc向上造型为父类型IUnionPay类型
再例如:
//因为ATMCBC类同时还实现了IPolice接口,
所以 IPolice pol=cbc;//编译正确:变量cbc同样可以向上造型为Ipolice类型
这里的父类型可以是 抽象类,也可以是 接口
向上造型的结果
父类型的变量,仅能使用子类型重写父类的方法。其它方法一概不能使用。
编译器在编译时,根据父类型中的方法定义,检查调用是否正确。
编译时,方法调用看变量
简单的记法:今后只要是在编译时,判断父类型的变量 能否调用子类型对象的方法,就要看等号左边的变量类型。
如果运行时,觉得父类型功能受限制,想用更多功能怎么办?
强转转换
可以通过强制转换将父类型变量转换为子类型变量
前提:要转化的变量所引用的对象,必须是目标类型的子类型或者就是目标类型本身。
例如:
- IPolice pol=new ATMCBC(); /父类型变量pol只能使用takePic方法,
- //声明子类型变量c ,可以使用所有子类型实现的方法
ATMCBC c= (ATMCBC)pol;
//编译正确。因为pol变量所指向的对象就是目标类型ATMCBC
IUnionPay p= (IUnionPay)pol;
//编译正确。因为pol指向的对象类型是目标类型IUnionPay的子类型
ATMABC aa=(ATMABC)pol;
//编译正确,但运行错误: ClassCastException
//因为pol指向的对象类型,不是ATMABC的子类型。
ATMABC aa= (ATMABC)pol;
//编译正确,但运行错误: ClassCastException
//因为pol指向的对象类型,不是ATMABC的子类型。
强转看对象!目标类型必须是对象类型本身或对象的父类型
instanceof关键字
·在强制转型中,为了避免出现ClassCastException,可以通过instanceof关键字判断某个引用指向的对象是否为指定类型。
·语法∶对象instanceof目标类型 pol instanceof ATMABC
·返回值:
- True :说明对象就是目标类型或者是目标类型的子类型,可以强转。
- False:说明不满足强转前提,不能强转。