通过之前对 JAVA基础 —— 面向对象 以及 JAVA基础 —— 面向对象内存图 的学习。
接下来我们将会进一步学习面向对象进阶的相关知识点。
static | JAVA基础 (面向对象进阶)—— Static |
继承 | JAVA基础 (面向对象进阶)—— 继承 |
多态 | JAVA基础 (面向对象进阶)—— 多态 |
包、final、权限修饰符、代码块、抽象类和抽象方法方法 | JAVA基础(面向对象进阶) —— 包、final、权限修饰符、代码块、抽象类和抽象方法方法 |
接口 | JAVA基础 (面向对象进阶)—— 接口 |
内部类 | JAVA基础 (面向对象进阶)—— 内部类 |
目录
一、前言
1. 字面意思:多态即是多种形态
下图的学生形态和人的形态就是多态下的两种形态。
2. 多态的应用场景
假如我们设计一个学生信息管理系统,其中包括三个对象,并且进行注册操作。
那我们应该怎么设计呢?
二、 内容概述
1. 什么是多态?
同类型的对象,表现出的不同形态。
2. 多态的表现形式
父亲类型 对象名称 = 子类对象
3. 多态的前提
- 有继承 / 实现关系
- 有父类引用指向子类对象
- 有方法重写
4. 多态的好处
使用父类型作为参数,可以接收所有子类对象
体现多态的扩展性与便利
5. 练习
一、2 上图所示
//Person.java 父类
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.java
public class Student extends Person{
@Override
public void show() {
System.out.println("学生信息为" + getName() + "," + getAge());
}
}
//Teacher.java
public class Teacher extends Person{
@Override
public void show() {
System.out.println("老师信息为" + getName() + "," + getAge());
}
}
//Administrator.java
public class Administrator extends Person{
@Override
public void show() {
System.out.println("管理员信息为" + getName() + "," + getAge());
}
}
//测试类
public class Test {
public static void main(String[] args) {
//创建三个对象 并调用register方法
Student s = new Student();
s.setName("张三");
s.setAge(23);
Teacher t = new Teacher();
t.setName("李华老师");
t.setAge(30);
Administrator a= new Administrator();
a.setName("管理员");
a.setAge(27);
//多态
//通过不同对象调用不同show方法
register(s);
register(t);
register(a);
}
//这个方法既能接收老师,又能接收学生,还能接收管理员
//只能把参数写成三个类型的父类
public static void register(Person p) {
p.show();
}
}
运行结果:
三、多态调用成员特点
- 变量调用:编译看左边,运行也看左边
- 方法调用:编译看左边,运行看右边
public class Test {
public static void main(String[] args) {
//创建对象(多态方式)
//Fu f = new Zi(父类类型)
Animal a =new Dog();
//调用成员变量:编译看左边 运行也看左边
//编译看左边: javac编译代码时,会看左边父类中有没有这个变量
//如果有 ,编译成功,如果没有,编译失败
//运行看左边:java运行代码时候,实际获取的就是左边弗雷中成员变量的值
System.out.println(a.name); //动物
//调用成员方法:编译看左边 运行看右边
//编译看左边:javac编译代码时,会看左边的父类中有没有这个方法
//如果有,编译成功 如果没有,编译失败
//运行看右边:java运行代码时,实际运行的是子类中的方法
a.show(); //Dog --- show 方法
}
}
class Animal{
String name = "动物";
public void show() {
System.out.println("Animal --- show 方法");
}
}
class Dog extends Animal{
String name = "狗";
@Override
public void show() {
System.out.println("Dog --- show 方法");
}
}
class Cat extends Animal{
String name = "猫";
@Override
public void show(){
System.out.println("Cat --- show 方法");
}
}
内存图:
四、 多态的优劣势
1. 多态的优势
- 在多态的形势下,右边对象可以实现解耦合,便于扩展和维护。
- 定于方法额时候,使用父类作为参数,可以接收所有子类对象,体现多态的扩展性和便利。
2. 多态的弊端
不能调用子类的特有功能。
- 当调用成员方法的时候,编译看左边,运行看右边。
- 那么在编译的时候先检查父类中有没有这个方法,如果没有直接报错。
3. 引用数据类型的类型转换有几种方式?
自动类型转换、强制类型转换
4.强制类型转换能解决什么问题?
- 可以转换成真正的子类类型,从而调用子类独有功能。
- 转换类型与真实对象类型不一致会报错
- 转换的时候用instanceof关键字进行判断