1.多态概述
1.多态是封装、继承之后,面向对象的第三大特性。
2.多态是面向对象程序设计(OOP)的一个重要特征,指同一个实体同时具有多种形式,即同一个对象,在不同时刻,代表的对象不一样,指的是对象的多种形态。
比如,你的女盆友让你买点水果回来,不管买回来的是苹果还是西瓜,只要是水果就行,这个就是生活中多态的体现。
再比如,小猫、小狗、小猪我们可以把他们都归纳成小动物,每种小动物都需要吃东西,所以我们可以统一设置他们都必须吃,但是每种小动物的习性不一样,那这个就可以设置成小动物自己特有的功能,多态对象只能调用父类中定义子类中重写的功能,并不能调用子类的特有功能,这样就实现了代码的统一。
2.特性
1.多态的前提:继承(要有子类和父类)
2..前提2:有方法重写(在子类里面重写父类已有的函数)
3.父类引用指向子类对象,定义格式:父类类型 变量名=new 子类类型();
如:Fruits a = new Grape();
4.多态中,编译看左边,运行看右边
多态:
Percent p = new Children();
对于成员方法:编译看左边,运行看右边。
对于成员变量:编译运行都看左边。也就是成员变量没有多态特性。
静态方法和变量:编译运行都看左边,同成员变量一样。
子类的同名的 类变量、静态方法、静态变量 不会覆盖父类。 调用p的这些属性找的是父类的属性
子类同名的类方法覆盖父类。 调用p的方法找的是子类的方法。
调用p的属性(变量或方法)会检查父类Percent是否存在此属性,如果不存在(只有子类有)或者父类属性用private修饰则编译不通过。
3. instanceof关键字
作用:instanceof 是 Java 的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型。
实例:摘自Instanceof关键字用法(Java基础)_辰兮要努力-CSDN博客_instanceof用法
instanceof 严格来说是Java中的一个双目运算符,用来测试一个对象是否为一个类的实例,用法为:
boolean result = obj instanceof Class
其中 obj 为一个对象,Class 表示一个类或者一个接口,当 obj 为 Class 的对象,或者是其直接或间接子类,或者是其接口的实现类,结果result 都返回 true,否则返回false。
创建person类
public class Person {
}
创建Student类
public class Student extends Person {
}
测试类:结果附后面
public class TestInstanceof {
public static void main(String[] args) {
Person p1 = new Person();
Person p2 = new Student();
Student m1 = new Student();
System.out.println(p1 instanceof Student);//false
System.out.println(p2 instanceof Student);//true
System.out.println(m1 instanceof Student);//true
System.out.println(p1 instanceof List);//false
System.out.println(p1 instanceof List<?>);//false
System.out.println(p1 instanceof String);//编译报错
System.out.println(p1 instanceof List<Person>);//编译报错
}
}
4.多态的转型--向上转型和向下转型
在JAVA中,继承是一个重要的特征,通过extends关键字,子类可以复用父类的功能,如果父类不能满足当前子类的需求,则子类可以重写父类中的方法来加以扩展。
那么在这个过程中就存在着多态的应用。存在着两种转型方式,分别是:向上转型和向下转型。
向上转型:可以把不同的子类对象都当作父类来看,进而屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,统一调用标准。
比如:父类Parent,子类Child
父类的引用指向子类对象:Parent p=new Child();
说明:向上转型时,子类对象当成父类对象,只能调用父类的功能,如果子类重写了父类中声明过的方法,方法体执行的就是子类重过后的功能。但是此时对象是把自己看做是父类类型的,所以其他资源使用的还是父类型的。
向下转型(较少):子类的引用的指向子类对象,过程中必须要采取到强制转型。这个是之前向上造型过的子类对象仍然想执行子类的特有功能,所以需要重新恢复成子类对象
Parent p = new Child();//向上转型,此时,p是Parent类型
Child c = (Child)p;//此时,把Parent类型的p转成小类型Child
其实,相当于创建了一个子类对象一样,可以用父类的,也可以用自己的
说明:向下转型时,是为了方便使用子类的特殊方法,也就是说当子类方法做了功能拓展,就可以直接使用子类功能。
5.多态实例
摘自:新手小白学JAVA 面向对象之多态_程序媛泡泡的博客-CSDN博客
创建包: cn.tedu.oop
创建类: TestDemo.java
package cn.tedu.oop2;
/*本类用作多态的入门案例*/
public class TestDemo {
public static void main(String[] args) {
//6.创建“纯纯的”对象用于测试
Animal a = new Animal();
Cat c = new Cat();
Dog d = new Dog();
a.eat();//小动物Animal吃啥都行~调用的是父类自己的功能
c.eat();//小猫爱吃小鱼干~调用的是子类重写后的功能
d.eat();//小狗爱吃肉骨头~调用的是子类重写后的功能
/*2.父类对象不可以使用子类的特有功能*/
//a.jump();//报错,Animal类里并没有这个方法
//a.run();//报错,Animal类里并没有这个方法
c.jump();//小猫Cat跳的老高啦~,子类可以调用自己的功能
d.run();//小狗Dog跑的老快啦~,子类可以调用自己的功能
//7.创建多态对象进行测试
/*3.口诀1:父类引用指向子类对象
* 解释:创建出来的子类对象的地址值,交给父类类型的引用类型变量来保存*/
Animal a2 = new Cat();//Cat类对象的地址值交给父类型变量a2来保存
Animal a3 = new Dog();//Dog类对象的地址值交给父类型变量a3来保存
//8.测试多态对象
/*4.口诀2:编译看左边,运行看右边
* 解释:必须要在父类定义这个方法,才能通过编译,把多态对象看作是父类类型
* 必须要在子类重写这个方法,才能满足多态,实际干活的是子类*/
a2.eat();//小猫爱吃小鱼干~,多态对象使用的是父类的定义,子类的方法体
}
}
/*1.多态的前提:继承+重写*/
//1.创建父类
class Animal{
//3.创建父类的普通方法
public void eat(){
System.out.println("小动物Animal吃啥都行~");
}
}
//2.1创建子类1
class Cat extends Animal{
//4.1添加重写的方法
public void eat(){
System.out.println("小猫爱吃小鱼干~");
}
//5.1添加子类的特有功能
public void jump(){
System.out.println("小猫Cat跳的老高啦~");
}
}
//2.2创建子类2
class Dog extends Animal{
//4.2添加重写的方法
@Override
public void eat(){
System.out.println("小狗爱吃肉骨头~");
}
//5.2添加子类的特有功能
public void run(){
System.out.println("小狗Dog跑的老快啦~");
}
}
6.最后
多态机制遵循的原则为:在满足多态的3个必要条件:继承、重写、向上转型后,对于被子类对象赋值的父类引用对象,如果子类重写了父类的方法,则运行时父类引用对象会调用子类的方法;如果子类继承了父类的方法(未重写),则运行时父类引用对象会调用父类的方法。但是父类引用对象依旧要根据继承链中方法调用的优先级来确认具体引用的方法,
优先级为:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。