重学java 24.面向对象 多态

news/2024/9/23 14:29:17/

下雨了,跑不跑衣服都会被淋湿,还不如慢慢地走,结局已定

                                                                                      —— 24.4.25

多态

1.面向对象三大特性:封装        继承        多态

2.怎么学:

        a、不要从字面意思上理解多态这两个字,要从使用形式上掌握

        b、要知道多态的好处

        c、要知道多态的前提(什么样的情况下才能形成多态)

一、多态的介绍和基本使用

1.前提:

        a、必须有子父类继承或者接口实现关系

        b、必须有方法的重写(没有重写,多态没有意义),多态主要是调用重写方法

        c、new对象:父类引用指向子类对象

                Fu fu = new Son() -> 理解为大类型接收了一个小类型的数据 -> 比如:double b = 10

2.注意:

        多态下不能直接调用子类特有功能

3.基本使用

抽象类

java">public abstract class Animal {public abstract void eat();
}

子类1

java">public class Dog extends Animal{@Overridepublic void eat() {System.out.println("狗啃骨头");}// 特有方法public void lookDoor(){System.out.println("狗会看门");}
}

子类2

java">public class Cat extends Animal{@Overridepublic void eat() {System.out.println("猫吃鱼");}// 特有方法public void catchmouse(){System.out.println("猫会抓老鼠");}
}

测试类

java">public class Demo122Test {public static void main(String[] args) {// 原始方法Dog dog = new Dog();// 重写的方法dog.eat();// 特有的方法dog.lookDoor();Cat cat = new Cat();// 重写的方法cat.eat();// 特有的方法cat.catchmouse();System.out.println("——————————————————————");// 多态形式new对象Animal animal = new Dog();// 相当于double b = 10// 重写的animal,接受的是dog对象,所以调用的是dog里的eat方法animal.eat();
//        animal.loolDoor();    多态前提下,不能直接调用子类特有成员Animal animal1 = new Cat();// cat重写的方法animal1.eat();}
}

二、多态的前提下成员访问特点

成员变量

父类

java">public class Fu {int num = 1000;
}

子类

java">public class Son extends Fu{int num = 100;
}

测试类

java">public class Demo123Test {public static void main(String[] args) {Fu fu = new Son();System.out.println(fu.num);}
}

成员变量看等号左边是谁,先调用谁中的成员变量

成员方法

父类

java">public class Fu {int num = 1000;public void method(){System.out.println("父类中的method方法");}
}

子类

java">public class Son extends Fu{int num = 100;public void method(){System.out.println("我是子类中重写的method方法");}
}

测试类

java">public class Demo123Test {public static void main(String[] args) {Fu fu = new Son();System.out.println(fu.num);// 父类中的numfu.method();// 我是子类中重写的method方法}
}

成员方法看new的是谁,先调用谁中的成员方法,子类没有找父类

三、多态的好处

1.问题描述:

        如果使用原始方式new对象等号左右两边一样),既能调用重写的,还能调用继承的,还能调用自己特有的成员

        但是多态方式new对象,只能调用重写的,不能直接调用子类特有的成员,那为啥还要用多态呢

2.多态方式和原始方式new对象的优缺点:

        原始方式:

                a、优点:既能调用重写的,又能调用继承的,还能调用自己特有的成员

                b、缺点:扩展性差,尤其是方法的参数传递

        多态方式:

                a、优点:扩展性强(父类可以接收其任意的子类)

                b、缺点:不能直接调用子类特有的功能

                        Fu fu = new Son();

                        double b = 10;

                        b = 100L;

形参传递父类类型,调用此方法父类型可以接收任意它的子类对象
传递哪个子类对象,就指向哪个子类对象,就调用哪个子类对象重写的方法

示例:

animal

java">public abstract class Animal {public abstract void eat();
}

cat

java">public class Cat extends Animal {@Overridepublic void eat() {System.out.println("猫吃鱼");}// 特有方法public void catchmouse(){System.out.println("猫会抓老鼠");}
}

dog

java">public class Dog extends Animal {@Overridepublic void eat() {System.out.println("狗啃骨头");}// 特有方法public void lookDoor(){System.out.println("狗会看门");}
}

test1

java">public class Demo124Test1 {public static void main(String[] args) {Dog dog = new Dog();
//      重写的方法dog.eat();
//      特有的方法dog.lookDoor();System.out.println("————————————————————");method(dog);Cat cat = new Cat();method(cat);}public static void method(Dog dog){dog.eat();dog.lookDoor();}public static void method(Cat cat){cat.eat();cat.catchmouse();}
}

test2

java">public class Demo125Test2 {public static void main(String[] args) {// 父类接收子类类型Animal animal = new Dog();animal.eat();animal = new Cat();animal.eat();// 传统方式接受类型Dog dog = new Dog();method(dog);Cat cat = new Cat();method(cat);}// 形参传递父类类型,调用此方法父类型可以接收任意它的子类对象// 传递哪个子类对象,就指向哪个子类对象,就调用哪个子类对象重写的方法public static void method(Animal animal){animal.eat();}
}

四、多态中的转型

1.向上转型

父类引用指向子类对象

        好比是:double b = 1;

2.向下转型

① 好比强转,将大类型强制转换成小类型

② 表现方式:

        父类类型 对象名1 = new 子类对象() ——> 向上转型 ——> double b = 1

        子类类型 对象名2 = (子类类型)对象名1 ——> 向下转型 ——> int i = (int)b

③ 想要调用子类特有的功能,我们就需要向下转型

3.案例

父类animal

java">public abstract class Animal {public abstract void eat();
}

子类cat

java">public class Cat extends Animal {@Overridepublic void eat() {System.out.println("猫吃鱼");}// 特有方法public void catchmouse(){System.out.println("猫会抓老鼠");}
}

子类dog

java">public class Dog extends Animal {@Overridepublic void eat() {System.out.println("狗啃骨头");}// 特有方法public void lookDoor(){System.out.println("狗会看门");}
}

测试类

java">public class Demo126Test01 {public static void main(String[] args) {// 多态new法Animal animal = new Dog();animal.eat();// dog重写的/*animal.lookDoor();// 多态不能调用子类特有功能*/// 向下转型 强转 就可以调用子类的特有功能Dog dog = (Dog) animal;dog.eat();dog.lookDoor();}
}

五、转型中可能出现的问题

1.类型转换异常(ClassCastException)

        如果等号左右两边类型不一致,则会出现类型转换异常(ClassCastException

                原因:当调用method传递Cat对象时,animal代表的就是cat对象
                此时,我们将代表cat对象的animal强转成了animal
                此时等号左右两边类型不一致了,所以出现了类型转换异常

java">public class Demo128Test {public static void main(String[] args) {Dog dog = new Dog();method(dog);System.out.println("——————————————————————————");Cat cat = new Cat();method(cat);}public static void method(Animal animal){// animal = dog// animal = catanimal.eat();/*这里会出现类型转换异常ClassCastException原因:当调用method传递Cat对象时,animal代表的就是cat对象此时,我们将代表cat对象的animal强转成了animal此时等号左右两边类型不一致了,所以出现了类型转换异常*/Dog dog = (Dog) animal;dog.lookDoor();}
}

2.解决:

        在向下转型之前,先判断类型

3.判断类型的方法:

        instanceof

        判断结果是boolean型

4.使用

        对象名 instanceof 类型 ——> 判断的是关键字前面的对象是否符合关键字后面的类型

5.示例

java">public class Demo128Test {public static void main(String[] args) {Dog dog = new Dog();method(dog);System.out.println("——————————————————————————");Cat cat = new Cat();method(cat);}public static void method(Animal animal){// animal = dog// animal = cat// animal.eat();/*这里会出现类型转换异常ClassCastException原因:当调用method传递Cat对象时,animal代表的就是cat对象此时,我们将代表cat对象的animal强转成了animal此时等号左右两边类型不一致了,所以出现了类型转换异常*/// Dog dog = (Dog) animal;// dog.lookDoor();if (animal instanceof Dog){Dog dog = (Dog) animal;dog.eat();dog.lookDoor();} else if (animal instanceof Cat) {Cat cat = (Cat) animal;cat.eat();cat.catchmouse();}}
}

六、综合练习

案例要求:       

        定义笔记本类,具备开机,关机和使用USB设备的功能。具体是什么USB设备,笔记本并不关心,只要符合USB规格的设备都可以。鼠标和键盘要想能在电脑上使用,那么鼠标和键盘也必须遵守USB规范,不然鼠标和键盘的生产出来无法使用;进行描述笔记本类,实现笔记本使用USB鼠标、USB键盘
USB接口,包含开启功能、关闭功能
笔记本类,包含运行功能、关机功能、使用USB设备功能
鼠标类,要符合USB接口
键盘类,要符合USB接口

定义USB接口:

java">public interface USB {// 开启功能public abstract void Open();// 关闭功能public abstract void Close();
}

笔记本类:

        接收USB接口和鼠标类键盘类对接口的具体实现,然后进行方法的定义,私有方法对接收的类用instanceof进行判断,然后不同类型不同实现

java">public class NoteBook {// 开机public void Start(){System.out.println("笔记本在运行");}// 关机public void Close(){System.out.println("笔记本关机");}// 关机/*USB usb = mouse 多态USB usb = keyBoard 多态*/public void UseUSB(USB usb){if(usb instanceof Mouse){Mouse mouse = (Mouse) usb;mouse.Open();mouse.click();mouse.Close();} else if (usb instanceof KeyBoard) {KeyBoard keyBoard = (KeyBoard) usb;keyBoard.Open();keyBoard.input();keyBoard.Close();}
//        usb.Open();
//        usb.Close();
//        System.out.println("使用USB功能");}
}

定义鼠标类,符合USB接口

        继承USB父类接口进行鼠标类Mouse具体的实现

java">public class Mouse implements USB {@Overridepublic void Open() {System.out.println("鼠标开启");}@Overridepublic void Close() {System.out.println("鼠标关闭");}// 特有方法public void click(){System.out.println("点击鼠标");}
}

定义键盘类,符合USB接口

        继承USB父类接口进行键盘类KeyBoard具体的实现

java">public class KeyBoard implements USB{@Overridepublic void Open() {System.out.println("键盘开启");}@Overridepublic void Close() {System.out.println("键盘关闭");}// 特有功能public void input(){System.out.println("敲击键盘");}
}

测试类

java">public class Demo129Test {public static void main(String[] args) {NoteBook noteBook = new NoteBook();Mouse mouse = new Mouse();noteBook.Start();// 多态的使用noteBook.UseUSB(mouse);noteBook.Close();System.out.println("——————————————————");KeyBoard keyBoard = new KeyBoard();noteBook.Start();// 多态的使用noteBook.UseUSB(keyBoard);noteBook.Start();}
}

运行结果

七、总结

1.接口

概述

        是一种引用数据类型,是一个标准,规则

⭐定义

        a、定义接口 —— public interface 接口名{}

        b、实现接口 —— public class 实现类 implements 接口{}

⭐抽象方法

        a、定义 —— public abstract 返回值类型 方法名(形参);

        b、使用 —— 实现类实现接口

                      —— 重写抽象方法

                      —— 创建实现类对象,调用重写方法 —— 接口不能new对象

默认方法

         a、定义 —— public default 返回值类型 方法名(形参){

                                       方法体;

                                       return;

                                }

         b、使用 —— 在实现类中可重写,可不重写

                       —— 创建实现类对象,调用默认方法

静态方法

        a、定义 —— public static 返回值类型 方法名(形参){

                                      方法体;

                                      return 结果;

                              }

        b、使用 —— 接口名直接调用

成员变量

        a、定义 —— public static final 数据类型 变量名 = 值

        b、使用 —— 接口名直接调用

⭐接口的特点

        a、接口可以多继承

        b、接口可以多实现

        c、一个类可以继承一个父类的同时实现一个或多个接口

接口的抽象类的区别

        a、相同点

                ① 都位于继承顶端,用于被其他类继承或者实现

                ② 都不能new

                ③ 都包含抽象方法,而且必须重写

        b、不同点

                ① 抽象类:一般作为父类使用,可有成员变量,构造方法,成员方法,抽象方法等

                ② 接口:成员单一,一般抽取接口,都是方法

                ③ 类不能多继承,接口可以

⭐2.多态

前提

        a、必须有子父类继承关系或者接口实现关系

        b、必须有方法的重写

        c、父类引用指向子类对象

成员访问特点

        a、成员变量 —— 看等号左边是谁

        b、成员方法 —— 看new的是谁

特点

        a、优点 —— 拓展性强

        b、缺点 —— 不能直接调用子类特有功能

转型

        a、向上转型 —— 父类引用指向子类对象

        b、向下转型 —— 将父类类型转成子类类型 —— 调用子类特有功能

        c、类型转换异常 —— ClassCastException

        d、类型判断 —— 对象名 instanceof —— 判断对象是否属于指定的类型


http://www.ppmy.cn/news/1440791.html

相关文章

书生·浦语大模型开源体系(四)笔记

💗💗💗欢迎来到我的博客,你将找到有关如何使用技术解决问题的文章,也会找到某个技术的学习路线。无论你是何种职业,我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章,也欢…

Typecho主题 - 一款视频ZeVideo开源主题

ZeVideo最为一款免费开源的视频主题,本次更新我们重构了代码结构。 全站pjax无刷新加载,支持根据系统进入深色模式,或手动切换,支持记录播放历史功能,首页布局支持自定义,主题设置支持修改logo&#xff0c…

debian gnome-desktop GUI(图形用户界面)系统

目录 🌞更新 🎨安装 🍎分配 🛋️重启 🔑通过VNC连接 debian gnome-desktop 🌞更新 sudo apt update sudo apt -y upgrade 🎨安装 sudo apt -y install task-gnome-desktop 这个过程比…

《深入浅出.NET框架设计与实现》笔记6.3——ASP.NET Core应用程序多种运行模式之三——桌面应用程序

ASP.NET Core应用程序可以在多种运行模式下运行,包括自宿主(Self-Hosting)、IIS服务承载、桌面应用程序、服务承载。 因此选择和时的模式很重要。 桌面应用程序 ASP.NET Core也可以用于构建跨平台的桌面应用程序,利用跨平台界面…

村集体建设用地,开发乡村旅游项目,土地如何审批?

以村集体建设用地,开发乡村旅游项目,土地如何审批? 乡村,作为承载乡村旅游产业的载体,在乡村振兴中扮演着非常重要的角色。 项目的落地,可靠的土地是必要的前提。集体建设用地如何审批?农转非又需要什么样的流程,具体…

自动化软件测试策略

作为一名软件开发人员,我在不同的公司工作过,具有不同的软件测试流程。在大多数情况下,没有特定/记录的测试方法......因此该过程的内容/方式取决于各个开发人员。与大多数情况一样,当没有强制执行或至少记录在案的政策时&#xf…

递归、搜索与回溯算法——穷举vs暴搜vs深搜

T04BF 👋专栏: 算法|JAVA|MySQL|C语言 🫵 小比特 大梦想 此篇文章与大家分享递归、搜索与回溯算法关于穷举vs暴搜vs深搜的专题 如果有不足的或者错误的请您指出! 目录 1.全排列1.1解析1.2题解 2.子集2.1解析2.1.1解法12.1.2解法1代码2.1.3解法22.1.4解法…

04.JAVAEE之线程2

1.线程的状态 1.1 观察线程的所有状态 线程的状态是一个枚举类型 Thread.State public class ThreadState {public static void main(String[] args) {for (Thread.State state : Thread.State.values()) {System.out.println(state);}} } NEW:Thread 对象已经有了.start 方…