什么是多态?
同类型的对象,表现出的不同形态。
多态的表现形式
父类类型 = 对象名称 = 子类对象;
多态的前提
有继承关系
有父类引用指向子类对象
有方法重写
多态的好处?
使用父类型作为参数,可以接受所有子类对象
体现多态的扩展性与便利
多态的应用场景
创建一个父类person
package PERSON;
//创建一个父类
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void show(){
System.out.println(name+" "+age);
}
}
创建一个子类student
package PERSON;
public class Student extends Person{
public void show(){
System.out.println("学生的信息为:"+getName()+" "+getAge());
}
}
创建一个子类teacher
package PERSON;
public class Teacher extends Person{
public void show(){
System.out.println("老师的信息为:"+getName()+" "+getAge());
}
}
创建一个子类administrators
package PERSON;
public class Administrators extends Person{
public void show(){
System.out.println("管理员的信息为:"+getName()+" "+getAge());
}
}
创建一个测试类
package PERSON;
public class Test {
public static void main(String[] args) {
Student student = new Student();
student.setName("小凯");
student.setAge(21);
Teacher teacher = new Teacher();
teacher.setName("王老师");
teacher.setAge(65);
Administrators administrators = new Administrators();
administrators.setName("管理员");
administrators.setAge(32);
register(teacher);
register(student);
register(administrators);
}
public static void register(Person b){
b.show();
}
}
多态调用成员的特点
变量调用:编译看左边,运行也看右边
方法调用:编译看左边,运行看右边
看下面代码
创建一个动物的父类
public class Animal {
String name ="动物";
public void show() {
System.out.println("1:Animal的show 方法");
}
}
再创建一个狗的子类
public class Dog extends Animal{
String lname= "狗";
public void show(){
System.out.println("Dog的show方法");
}
public viod eat(){
System.out.println("Dog的eat的方法");
}
}
再创建一个猫的子类
public class Cat extends Animal{
String name ="猫";
public void show() {
System.out.println("猫的show方法");
}
}
在测试类看上面的两个特点
public class test_Animal {
public static void main(String[] args) {
Animal animal = new Dog();
System.out.println(animal.name);
}
}
调用成员变量:编译看左边,运行也看左边
编译看左边,javac编译代码的时候,会看左边的父类中有没有这个变量,如果有,编译成功,如果没有编译失败,运行也看左边:java运行代码的时候,实际获取的就是左边父类中成员变量的值。
public class test_Animal {
public static void main(String[] args) {
Animal animal = new Dog();
animal.show();
}
}
调用成员方法:编译看左边,运行看右边
编译看左边:javac编译代码的时候,会看左边的父类中有没有这个方法,如果有,编译成功,如果没有编译失败。运行看右边:java运行代码的时候,实际上运行的是子类中的方法。
简单理解就是:这里的成员变量animal属于Animal类,所以在调用成员变量时,都会默认从Animal类中去找
成员方法:如果子类对方法进行了重写,那么在虚方法中是会把父类的方法进行覆盖的。
多态的优势和弊端
在多态形态下,右边对象可以实现解耦合,便于扩展和维护
定义方法的时候,使用父类型作为参数,可以接受所有子类对象,体现了多态的的扩展性与便于。
优势,在方法中,使用父类型作为参数,可以接受所有子类对象。
person p = new student();
p.work(); //当业务逻辑发生改变时,后续代码无需修改
他的好处就是,扩展性强,让代码更灵活,提高代码的复用性
多态的弊端:
不能调用子类中没有重写父类中的方法
public class test_Animal {
public static void main(String[] args) {
Animal animal = new Dog();
animal.eat();//报错!
}
}
解决的办法:
变回子类类型就可以了
public class test_Animal {
public static void main(String[] args) {
Animal animal = new Dog();
Dog animal = (Dog) animal;
animal.eat();
}
}
/*
先判断a是否为Dog类型,如果是,则强转换成Dog类型,转换之后变量名为d
如果不是,则不会墙砖,结果直接是false
*/
if(a instanceof Dog d){
d.eat();
}else if(a instanceof Cat c){
c,eat();
}else{
System.out.println("没有这个类型。无法转换");
}