继承和多态

目录:

1. 继承

2. 多态:

             转型 

             重写

正文:

1. 继承:

观察以下代码:

我们发现Cat类和Dog类中有许多相同的属性,那不妨思考一下是否能有一种办法能把它们的相同点都归结到一块儿呢?

当然有,它就是继承!!!

Cat类:

public class Cat {
    public String name;
    public int age;
    
    public void eat() {
        System.out.println(this.name + "正在吃饭...");
    }
    
    public void mimi() {
        System.out.println( this.name + "正在咪咪叫...");
    }
    
}

Dog类:

public class Dog {
    public String name;
    public int age;

    public void eat() {
        System.out.println(this.name + "正在吃饭...");
    }

    public void bark() {
        System.out.println(this.name + "正在汪汪叫...");
    }
}

继承的定义:

继承允许一个类(称为子类或派生类)基于另一个类(称为父类、基类或超类)来定义自己的特性和行为。通过继承,子类可以获得父类的属性和方法,并可以在此基础上进行扩展或修改,从而实现代码的重用和扩展。

简单来说就是对每个类的共性进行抽取,实现代码的复用。

那我们就可以对Dog和Cat的共性进行抽取了:

public class Animal {
    public String name = "小黑";
    public int age;

    public void eat() {
        System.out.println(this.name + "正在吃饭...");
    }
}

在我们抽取完成后应该借用关键字extends来让子类继承Animal:

Cat类:

public class Cat extends Animal{
    public String name;

    public void mimi() {
        System.out.println( this.name + "正在咪咪叫...");
    }

}

Dog类:

public class Dog extends Animal{
    public String name = "小白";

    public void bark() {
        System.out.println(this.name + "正在汪汪叫...");
    }
}

Test类:

public class Test {
    public static void main(String[] args) {
        Dog dog1 = new Dog();
        dog1.bark();
    }
}

运行结果:

观察运行结果可以看出调用的方法在哪个类里面,name就用谁的。

如果我们就是想要调用父类的成员变量怎么办?

这就需要用到关键字super。

修改后的Dog类:

public class Dog extends Animal{
    public String name = "小白";

    public void bark() {
        System.out.println(super.name + "正在汪汪叫...");
    }
}

运行结果: 

Creature类:

public class Creature {
    public String name = "大黄";
}

Animal类: 

public class Animal extends Creature{
    public String name = "小黑";
    public int age;

    public void eat() {
        System.out.println(this.name + "正在吃饭...");
    }
}

Dog类:

public class Dog extends Animal{
    public String name = "小白";

    public void bark() {
        System.out.println(super.name + "正在汪汪叫...");
    }
}

  super只能指代当前类的父类,不能指代父类的父类,甚至继续往上指代。

注:super就是一个关键字,来提高代码的可读性!!!

在Java中没有多继承:(但我们可以通过接口的形式支持多继承)

 在写继承的时候如果有太多层的话会导致整个代码比较杂乱,我们一般最多写2~3层。

如果我们想要一个类不能再被继承,这里我们可以使用final关键字来修饰这个类:

如果一个类被final给修饰了,当这个类被继承的时候编译器就会报错。(final就是起到一个标记的作用)

 当子类继承父类之后,如果父类的构造方法是有参数的,子类需要显示父类的构造方法,要先帮助父类的成员进行初始化。

 还需要注意的一点是super()必须在第一行,由此推出super()和this()是无法共存的:

 

 观察下面的代码,试着猜一下运行结果是什么?

Dog类:

public class Dog extends Animal{
    {
        System.out.println("Dog类的实例代码块被执行了...");
    }
    public Dog(String name, int age) {
        super(name, age);
        System.out.println("Dog类的构造方法被执行了...");
    }

    static {
        System.out.println("Dog类的静态代码块被执行了...");
    }
    public void bark() {
        System.out.println(super.name + "正在汪汪叫...");
    }
}

Animal类:

public class Animal extends Creature{
    public String name;
    public int age;

    {
        System.out.println("Animal类的实例代码块被执行了...");
    }
    static{
        System.out.println("Animal类的静态代码块被执行了...");
    }
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("Animal类的构造方法被执行了...");
    }

    public void eat() {
        System.out.println(this.name + "正在吃饭...");
    }
}

Test类:

public class Test {
    public static void main(String[] args) {
        Dog dog1 = new Dog("小黑", 5);
    }
}

结论:

先执行父类和子类的静态代码块;

再执行父类的实例代码块和构造方法;

最后执行子类的实例代码块和构造方法。

注:关于代码块,在《类和对象详解》的博客中有讲解。

 运行结果:

 2. 多态:

先给一个现象让我们看一下它到底是什么:

Shape类:

public class Shape {
    public double area;
    public double cir;

    public Shape(double area, double cir) {
        this.area = area;
        this.cir = cir;
    }

    public void draw() {
        System.out.println("画一个图形...");
    }
}

Tri类:

public class Tri extends Shape{

    public Tri(double area, double cir) {
        super(area, cir);

    }

    public void draw() {
        System.out.println("画一个面积为 " + this.area +" 周长为 "+ this.cir+ "的三角形...");
    }
}

Rot类:

public class Rot extends Shape{

    public Rot(double area, double cir) {
        super(area, cir);
    }

    public void draw() {
        System.out.println("画一个面积为 " + this.area +" 周长为 "+ this.cir+ "的圆...");

    }
}

Test类: 

public class Test {
    public static void todraw(Shape shape) {
        shape.draw();
    }
    public static void main(String[] args) {
        Shape shape1 = new Rot(5, 10);
        todraw(shape1);

        Shape shape2 = new Tri(2,5);
        todraw(shape2);
    }
}

运行结果:

此时就是发生了多态,通俗地来讲,就是多种形态,具体点就是去完成某些行为,当不同的对象去完成的时候会产生不同的结果。

程序在编译的时候确实调用的是父类的draw() 方法,当代码运行时,通过父类引用,调用了父类和子类重写的那个方法,结果实际调用了子类的方法,此时我们把这种情况叫做动态绑定。(大前提:一定是在继承的情况下)

当然,这里也涉及到了向上转型和重写的问题,接下来我就详细讲一下什么是转型和重写?

转型:

举个例子:

比如说父类为Animal,Dog和Cat都是它的子类,这时他们之间就可以发生转型。

Animal animal = new Dog();

 

上面这段代码就是发生了向上转型,一共有三种方式发生向上转型:

1. 直接赋值:

Animal animal = new Dog();

2. 方法的传参:

public static void func(Animal animal) {}
public static void main(String[] args){
      Dog dog = new Dog();
      func(dog);
}

3. 返回值:

public static Animal func(){
      Dog dog = new Dog();
      return dog;
}
public static void main(String[] args){
           Animal animal = func();
}

 

向上转型的缺陷:

通过父类的引用调用子类特有的方法是无法直接实现的,这里只能调用父类自己的。

 

当然,有向上转型就会有向下转型。

向下转型,例:

Animal animal = new bird();
Bird bird = (bird)animal;
bird.fly();

 但是并非所有的向下转型都能成功,例:

Animal animal = new Dog();
Bird bird = (bird)animal;
bird.fly();

 

重写:

观察下面代码:

Shape类:

public class Shape {
    public double area;
    public double cir;

    public Shape(double area, double cir) {
        this.area = area;
        this.cir = cir;
    }

    public void draw() {
        System.out.println("画一个图形...");
    }
}

Rot类: 

public class Rot extends Shape{
    public Rot(double area, double cir) {
        super(area, cir);
    }

    @Override
    public void draw() {
        System.out.println("画一个面积为 " + this.area +" 周长为 "+ this.cir+ "的圆...");

    }
}

Tri类:

public class Tri extends Shape{
    public Tri(double area, double cir) {
        super(area, cir);
    }

    @Override
    public void draw() {
        System.out.println("画一个面积为 " + this.area +" 周长为 "+ this.cir+ "的三角形...");
    }
}

 Test类:

public class Test {
    public static void todraw(Shape shape) {
        shape.draw();
    }
    public static void main(String[] args) {
        Shape shape1 = new Rot(5, 10);
        todraw(shape1);

        Shape shape2 = new Tri(2,5);
        todraw(shape2);
    }
}

 运行结果:

 程序在编译的时候确实调用的是父类的draw() 方法,当代码运行时,通过父类引用,调用了父类和子类重写的那个方法,结果实际调用了子类的方法,此时我们把这种情况叫做动态绑定。(大前提:一定是在继承的情况下)

注:动态绑定是理解多态的基础!!!

构成重写时父类和子类的两个方法应该满足的条件:

1. 方法名相同;

2. 参数列表相同(个数,类型,顺序);

3. 返回值类型相同。 

仔细观察可以发现在上面的代码有一段这样的代码:

    @Override

 

这个代码叫做注解,注解有很多种,@Override只是其中之一,它是用来修饰被重写的方法,起到一个提示作用,如果在它下面的方法不满足重写的条件,编译器就会报错...

 

 重写的注意事项:

1. 不能是一个静态方法;

 (有人可能会觉得是子类中的方法没有加static,这里我把加了的截图也放在下面,编译器一样是报错的。)

 

2. 被final修饰的方法不能被重写(被final修饰的方法也叫作密封方法);

 

3. 如果子类重写父类的方法,子类的权限要大于要大于等于父类的权限;

 

4. 被private修饰的方法是不能被重写的;

 

5. 要构成父子关系。

 

 面试考点:

重载与重写的区别

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/638323.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【html】网页布局模板01---简谱风

模板效果: 这是一种最简单,最干净的一种网页布局。 模板介绍: 模板概述: 这个模板是一个基础的网页布局模板,包括一个头部区域(header),其中包含网站标题(logo)和导航菜单(nav),以及一个页脚区域(copy),用于显示版权信息。整体布局简洁明了,适合作为各种类…

构建全面的无障碍学习环境:科技之光,照亮学习之旅

在信息与科技日益发展的当下,为所有人群提供一个包容和平等的学习环境显得尤为重要,特别是对于盲人朋友而言,无障碍学习环境的构建成为了一项亟待关注与深化的课题。一款名为“蝙蝠避障”的辅助软件,以其创新的设计理念与实用功能…

贪心算法--区间调度问题

贪心算法 引言 贪心算法是一种简单而有效的算法设计技巧,在解决一些优化问题时具有广泛的应用。其基本思想是通过每一步的局部最优选择,最终达到全局最优解。贪心算法通常不会回溯之前的决策,而是根据当前状态作出最优决策,因此…

d20(184-190)-勇敢开始Java,咖啡拯救人生

目录 网络通信 网络通信三要素(IP地址,端口号,协议 IP地址 InetAddress 端口号 协议 传输层的两个通信协议 UDP通信 java.net.Datagramsocket类 客户端 服务端 UDP通信多收多发 客户端 服务端 TCP通信 java.net.Socket类 客…

UWA DAY 2024 正式启动|创新潜藏无限可能

备受期待的UWA DAY 2024即将盛大开幕!由侑虎科技UWA主办的这场年度游戏开发者大会,以“创新潜藏无限可能”为主题,致力于为游戏开发者呈现最前沿的技术盛宴。 大会定于2024年9月7日至9月8日(周六、周日)在上海举行&am…

YOLOv9改进策略 | 图像去雾 | 利用图像去雾网络UnfogNet辅助YOLOv9进行图像去雾检测(全网独家首发)

一、本文介绍 本文给大家带来的改进机制是利用UnfogNet超轻量化图像去雾网络,我将该网络结合YOLOv9针对图像进行去雾检测(也适用于一些模糊场景),我将该网络结构和YOLOv9的网络进行结合同时该网络的结构的参数量非常的小,我们将其添加到模型里增加的计算量和参数量基本可…

【R语言】ggplot中点的样式shape参数汇总

ggplot中点的样式展示&#xff1a; library(ggplot2)# 创建数据框 a<- data.frame(x 0:25, y 0:25) # 创建散点图 ggplot(a, aes(x x, y y, shape as.factor(y))) geom_point(size 4) scale_shape_manual(values 0:25) labs(shape "形状") theme(legend.…

k8s二进制安装与部署

目录 一、实验目的 二、实验环境 三、实验步骤 3.1 操作系统初始化配置 3.2 部署 docker引擎 3.3 部署 etcd 集群 3.3.1 在 master01 节点上操作 ​3.3.2 在 node01 节点上操作 3.3.3 在 node02 节点上操作 3.4 部署 Master 组件 3.4.1 在 mast…

【QT实战】汇总导航

✨Welcome 大家好&#xff0c;欢迎来到瑾芳玉洁的博客&#xff01; &#x1f611;励志开源分享诗和代码&#xff0c;三餐却无汤&#xff0c;顿顿都被噎。 &#x1f62d;有幸结识那个值得被认真、被珍惜、被捧在手掌心的女孩&#xff0c;不出意外被敷衍、被唾弃、被埋在了垃圾堆…

EN6347QI 开关稳压器 4A 贴片QFN-38 参数资料 应用案例 相关型号

EN6347QI 是一款直流/直流开关转换器。它是一款高效率的 buck (降压) 转换器&#xff0c;内置了电感器&#xff0c;能够提供高达 4A 的输出电流。其工作电压范围为 4.5V 至 12V&#xff0c;输出电压可调&#xff0c;最高可达 15V。EN6347QI 适合于各种电子设备中&#xff0c;用…

C#学习指南:重要内容与实用技巧

学习C#编程是一段充满挑战但又非常充实的旅程。以下是我在学习过程中积累的一些经验&#xff0c;希望能对大家有所帮助。 一、掌握基础概念 类及其成员 C#中的类是编程的基础模块。理解类的结构、属性、方法和构造函数是至关重要的。每个类都有其特定的功能&#xff0c;学会如…

【Linux网络编程】IO多种转接之Reactor

Reactor 点赞&#x1f44d;&#x1f44d;收藏&#x1f31f;&#x1f31f;关注&#x1f496;&#x1f496; 你的支持是对我最大的鼓励&#xff0c;我们一起努力吧!&#x1f603;&#x1f603; 基于上一篇epoll的学习&#xff0c;现在我们也知道epoll的工作模式有两种&#xff0c…

JavaScript Window对象

一、BOM&#xff08;浏览器对象模型&#xff09; window对象是一个全局对象&#xff0c;也可以说是JavaScript中的顶级对象。 像document、alert()、console.log()这些都是window的属性&#xff0c;基本BOM的属性和方法都是window的。 所有通过var定义在全局作用域中的变量、…

JAVASE之类和对象(1)

路虽远&#xff0c;行则将至&#xff1b;事虽难&#xff0c;做则必成。 主页&#xff1a;趋早——Step 专栏&#xff1a;JAVASE gitte&#xff1a;https://gitee.com/good-thg 引言&#xff1a; 这篇文章我们只介绍前半部分&#xff0c;下一篇文章会介绍剩下的部分。 目录 一、…

电路仿真软件:点亮教学新篇章,十大便利助力高效学习

在信息化时代的浪潮中&#xff0c;电路仿真软件以其独特的优势&#xff0c;逐渐在教学领域崭露头角。它不仅能够帮助学生更好地理解电路知识&#xff0c;还能提升教师的教学效果。接下来&#xff0c;让我们一起探讨电路仿真软件对教学带来的十大便利。 一、直观展示电路原理 电…

自用网站合集

总览 线上工具-图片压缩 TinyPNG线上工具-url参数解析 线上工具-MOV转GIF UI-Vant微信小程序版本其他-敏捷开发工具 Leangoo领歌 工具 线上工具-图片压缩 TinyPNG 不能超过5m&#xff0c;别的没啥缺点 线上工具-url参数解析 我基本上只用url参数解析一些常用的操作在线…

MSI U盘重装系统

MSI U盘重装系统 1. 准备一块U盘 首先需要将U盘格式化&#xff0c;这个格式化并不是在文件管理中将U盘里面的所有东西都删干净就可以了&#xff0c;需要在磁盘管理中&#xff0c;将这块U盘格式化&#xff0c;如果这块U盘有分区的话&#xff0c;那将所有的分区都格式化并且删除…

非阻塞sokcet和epoll

在Muduo网络库中同时使用了非阻塞socket与epoll&#xff0c;在此简单梳理下。 非阻塞sokcet和epoll共同工作的过程主要涉及网络编程中的非阻塞I/O和事件驱动机制。下面将详细解释这两者如何协同工作&#xff1a; 非阻塞socket简介 在传统的阻塞socket编程中&#xff0c;当调用…

springboot-阿里羚羊 服务端埋点

官方文档 集成Java SDK 手动引入jar包「quickaplus-log-collector-java-sdk-1.0.1-SNAPSHOT.jar」 <dependency><groupId>com.alibaba.lingyang</groupId><artifactId>quickaplus-log-collector-java-sdk</artifactId><version>1.0.1&l…

老Java学 Go 笔录(二) 从 go 的编译开始学起

目录 一.版本选择二.环境准备三.工具的选择四.第一个 hello go4.1 开发4.2 编译4.3 编译运行4.4 直接安装 五.用 go 快速搭建 webserver六.调用外部三方方法七.go vs java 的执行 前言 专栏旨在利用现有的 java 体系内容去完成 go 语言的学习. 本次行文是在 https://go.dev/doc…