多态
2025年3月18日大约 3 分钟
多态
多态:同一个对象,在不同时刻,表现出不同的形态
多态的概念和用法
- 多态是在继承/实现下的一种形象
- 具体表现: 对象多态 和 行为多态
- 多态的前提:
- 有继承/实现关系
- 父类引用指向子类对象(对象多态)
- 存在方法重写(行为多态)
// 测试类
public class Test{
public static void main(String[] args){
// 对象多态
Human liHua = new Chinese();
Human cliff = new American();
// 行为多态
liHua.speak(); // 输出:你好
cliff.speak(); // 输出:Hello
}
}
// 父类
public class Human{
public void speak(){
System.out.println();
}
}
// 子类
public class Chinese extends Human{
@Override
public void speak(){
System.out.println("你好");
}
}
// 子类
public class American extends Human{
@Override
public void speak(){
System.out.println("Hello");
}
}
多态的注意事项
- 在使用父类创建的对象,调用时
- 方法: 编译时会先检查父类是否有此方法,调用时会优先调用子类的方法\
- 成员变量: 编译时和运行时都调用父类的成员变量
- 父类引用指向子类对象,不能调用子类特有的方法,解决方法 多态的类型转换
多态的优点
- 右边对象是解耦合的,提高代码的可扩展性和可维护性
- 解耦合: 降低类之间的耦合性,不容易出现牵一发而动全身的现象
- 可扩展性: 当需要扩展功能时,只需要创建子类,重写父类的方法即可
- 可维护性: 当需要修改功能时,只需要修改子类的方法即可
- 父类类型的变量作为参数,可以接收所有子类对象
// 测试类
public class Test{
public static void main(String[] args){
Chinese liHua = new Chinese();
American cliff = new American();
// 2.可以接收所有子类对象
speak(liHua); // 输出:你好
speak(cliff); // 输出: Hello
}
// 1.父类类型的变量作为参数
public void speak(Human human){
human.speak();
}
}
- 父类类型的变量作为返回值,可以返回所有子类对象
多态的类型转换
- 自动类型转换: 父类 变量名 = new 子类();
- 强制类型转换: 子类 变量名 = (子类) 父类变量名;
为什么要进行类型转换
父类引用指向子类对象,不能调用子类特有的方法
如下面这种情况:
// 测试类
public class Test{
public static void main(String[] args){
//父类引用指向子类对象
Human liHua = new Chinese();
//必须要强制类型转换才能使用特有的方法
((Chinese)liHua).special(); // 输出:我的祖籍在中国
}
}
public class Chinese(){
public void special(){
System.out.println("我的祖籍在中国");
}
}
但是这样仍然不够标准,具体为什么看下面说明
类型转换的注意事项
- 在进行强制类型转换时,只要存在继承/实现关系编译就不会报错
但如下面所示,在运行时会报 ClassCastException 错误:
// 测试类
public class Test{
public static void main(String args[]){
// 父类引用指向子类对象
Human liHua = new Chinese();
// 强制类型转换
American TransliHua = (American)liHua;
}
}
因此需要使用 instanceof 关键字进行判断,判断父类引用指向的对象是否是子类对象
变量名 instanceof 对象
// 测试类
public class Test{
public static void main(String args[]){
// 父类引用指向子类对象
Human liHua = new Chinese();
// 强制类型转换
if(liHua instanceof Chinese){
Chinese TransliHua = (Chinese)liHua;
} else {
System.out.println("类型转换错误");
}
}
}