Java学习笔记@多态
笔者:unirithe
日期:11/09/2021
多态
同类型的对象,执行同一个行为,表现出不同的行为特征
常见形式
父类类型 对象名称 = new 子类构造器;
接口 对象名称 = new 实现类构造器;
abstract class Animal{
public void run(){}
}
class Dog extends Animal{
@Override
public void run() {
System.out.println("小狗跑");
}
}
class Demo{
public static void main(String[] args) {
Animal d = new Dog();
d.run();
}
}
成员访问特点
- 方法调用:编译看左,运行看右
- 变量调用:编译看左,运行也看左
(多态侧重行为多态)
import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;
class Animal{
public String type = "动物";
public void printType(){
System.out.println(this.type);
}
}
class Dog extends Animal{
public String type = "小狗";
@Override
public void printType() {
System.out.println(this.type);
}
}
class Demo{
public static void main(String[] args) {
Animal a = new Dog();
System.out.println(a.type); // 调用变量,输出:动物
a.printType(); // 调用方法,输出: 小狗
}
}
多态前提
- 继承 / 实现关系
- 有父类引用指向子类对象
- 有方法重写
多态优势
解耦合
在多态形势下,右边对象可以实现解耦合,便于扩展和维护
Animal a = new Dog();
a.run();
// 后续业务行为随new的对象而变,后续代码无需修改
高扩展与便利
定义方法时使用父类型作为参数,该方法就可以接受父类的一切子类对象
import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;
abstract class Animal{
void run(){};
}
class Dog extends Animal{
@Override
void run() {
System.out.println("小狗跑");
}
}
class Demo{
public static void main(String[] args) {
Animal a = new Dog();
go(a);
}
public static void go(Animal a){
System.out.println("开始");
a.run();
System.out.println("结束");
}
}
多态的问题 :多态下不能使用子类的独有功能
类型转换
自动类型转换(从子到父)
子类对象赋值给父类类型的变量指向
强制类型转换(从父到子)
此时必须进行强制类型转换,即子类 对象变量 = (子类) 父类类型的变量
作用:解决多态下的劣势,可实现调用子类独有的功能
注意:如果转型后的类型和对象真实类型不是同一种类型,那么在转换的时候就会出现ClassCastException,例如:
Animal a = new Cat();
Dog b = (Dog) a; // 报错
防止出现这个问题可以在转换前使用 instanceof 判断当前对象的真实类型
变量名 instanceof 真实类型
判断关键字左边的变量指向的对象的真实类型,是否是右边的类型或其子类类型,则返回true,否则返回false
Animal a = new Cat();
Dog b = null;
if (a instanceof Dog)
b = (Dog) a;
总结
- 引用数据类型的类型转换的两种方式
- 自动类型转换
- 强制类型转换
- 强制类型转换解决什么问题?需要注意什么?
- 可转换成真正的子类类型,从而调用子类独有功能
- 有继承 / 实现的 2个类型就可以进行类型转换,编译无问题
- 运行时,若发现强制转换的类型不是对象真实类型则报错
- 类型转换异常:
ClassCastException
多态案例(USB设备)
需求: 使用面向对象编程,设计可安装2个USB设备的电脑对象
- 鼠标:被安装时可接入、点击、拨出
- 键盘:被安装时刻接入、打字、拨出
分析:
- USB接口:接入和拔出
- USB实现类:分别表示鼠标和键盘,实现USB接口
- 电脑对象:创建2个USB实现类对象
import java.security.Key;
interface USB{
void connect();
void unConnect();
}
class KeyBoard implements USB{
private String name;
public KeyBoard(String name) {
this.name = name;
}
@Override
public void connect() {
System.out.println(name + " 连接成功!");
}
@Override
public void unConnect() {
System.out.println(name + " 断开连接!");
}
public void onKnock(){
System.out.println(name + "敲击了一下.");
}
}
class Mouse implements USB{
private String name;
public Mouse(String name) {
this.name = name;
}
@Override
public void connect() {
System.out.println(name + " 连接成功!");
}
@Override
public void unConnect() {
System.out.println(name + " 断开连接!");
}
public void onClick(){
System.out.println(name + " 点击了一下.");
}
}
class Computer{
private String name;
public Computer(String name) {
this.name = name;
}
public void connectUSB(USB usb){ // 多态
usb.connect();
if(usb instanceof KeyBoard) {
KeyBoard k = (KeyBoard) usb;
k.onKnock();
} else if (usb instanceof Mouse){
Mouse m = (Mouse) usb;
m.onClick();
}
}
public void start(){
System.out.println(name + " 启动成功!");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class Demo{
public static void main(String[] args) {
Computer c = new Computer("笔记本");
c.start();
USB u1 = new KeyBoard("机械键盘");
c.connectUSB(u1);
USB u2 = new Mouse("鼠标");
c.connectUSB(u2);
}
}

浙公网安备 33010602011771号