Java面向对象:抽象类的学习

news2024/10/7 12:23:53

本文介绍了抽象类的基本语法概念,什么是抽象类. Java中抽象类的语法,抽象类的特性
抽象类的作用(抽象类和普通类的区别) 用抽象类实现多态…

抽象类的学习

  • 一.什么是抽象类
  • 二.抽象类语法
  • 三.抽象类的特性
  • 四.抽象类的作用
  • 五. 抽象类实现多态

一.什么是抽象类

在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类

比如:
狗类和猫类都是一个完整的对象,它们具备自己的行为和属性,同时也有相同的属性和行为,这些相同的属性行为也就是所有动物所具备的,
有这层关系后,便可以把这些共同具备的属性和行为抽取出来形成一个动物类
在这里插入图片描述
狗类和猫类都能具体描述出狗对象和猫对象,而动物类内部并没有足够的信息来描述一个准确的对象,因此,动物类可以被设置为抽象类…

当我们想描述一个图形时,能定义一个图形类,但是图形并不具体,没有完整的信息表示具体是什么图形,但所有具体的图形(如:三角形 圆形)都有图形共同具备的属性和行为
在这里插入图片描述
图形类派生出 圆形类和矩形类,图形类即是一种抽象的类它并不能具体表示哪种图形,它可以作为具体图形的基类给其提供图形本身具备的属性和行为,而具体图形具有图形的属性和行为和自身的属性和行为构成一个完整的类

在打印图形例子中, 我们发现, 父类 Shape 中的 draw 方法好像并没有什么实际工作, 主要的绘制图形都是由 Shape的各种子类的 draw 方法来完成的.

像这种没有实际工作的方法, 我们可以把它设计成一个 抽象方法(abstractmethod), 包含抽象方法的类我们称为 抽象类(abstract class).

动物类和图形类,本身都是一个普通的类,这些类通常都是具备其他类共有的属性而被抽取出来所形参的类,由于其并不能完整的描述对象 所以这些类都是抽象的, 在编写代码中一般也不会对其实例化,即抽象类存在的最大意义就是用来被继承的…

当一个类不能完整的描述一个对象时 可以选择将其属性方法补全能描述一个具体对象 或者最好在语法上将其设置为抽象类

二.抽象类语法

在Java中,一个类如果被 abstract 关键字修饰后即称为抽象类,抽象类中被 abstract 修饰的方法称为抽象方法,抽象方法不用给出具体的实现体。

示例:

abstract class Shape{   
   
    //抽象类中有抽象方法 也有非抽象方法  普通类只有非抽象方法
     void draw(){ //抽象类中的非抽象方法 可以写方法体
        System.out.println("画图");   
    }
    Shape(){ //构造方法

    }
    String name;
    abstract  void func();  
    //抽象类中方法 也可以不写方法体 不写方法体时要在前面加abstract 为抽象方法 方法后加分号
   
}

class Circle extends Shape{
    @Override
    void draw(){  //可以对抽象类 有方法体的方法进行重写 也可以不重写
        System.out.println("画圆圈○");
    }
    void func(){  // 必须对继承的抽象类的抽象方法进行(实现) 否则无法编译通过
       //super.func(); 编译错误 在子类方法里不能通过super访问父类抽象方法 因为其没有方法体
        System.out.println("实现父类的抽象方法");

    }
}

class Flower extends Shape{
    @Override
    void func(){  //即便方法体没内容也得重写抽象方法

    }
    @Override void draw(){
        System.out.println("画花❀");
    }
}

class Rect extends Shape{   //按住ant加回车 回车 快捷出现 重写 父类的抽象方法

    @Override
    void func() {

    }
    void draw(){
        System.out.println("画矩形!");
    }
}
public static void main(String[] args) {
        Circle circle=new Circle();
        circle.draw(); //当子类没有重写 父抽象类的 有方法体的方法 会调用父类的 重写了则调用子类的
        circle.func(); //子类必须实现父类抽象方法 否则编译不通过 因为父类抽象方法没有具体方法体不能被调用
        Shape shape=circle;
        shape.func();   // 抽象类可以实现向上转型 动态绑定 多态 此时 func方法 被子类func实现重写了 调用的是这个子类方法
        }
 }

抽象类 它的目的就是为了派生出子类 子类有自己的成员和父类的成员负责具体描述对象
在这里插入图片描述
子类里可以调用子类对象的方法,没有重写抽象父类的非抽象方法则调用的是父类非抽象方法.而调用的抽象方法一定是子类重写的父类抽象方法(抽象方法一定要被重写)

注意:

抽象类也是类,内部可以包含普通方法和属性,甚至构造方法
抽象类中可以有抽象方法和非抽象方法 即被abstract修饰的方法为抽象方法
非抽象方法需要有方法体(具体的方法实现) 被子类继承后可以重写其方法或者不重写
抽象方法不能写方法体但是其子类一定要重写父类的抽象方法(除非子类也是个抽象类)
在子类对象内不能通过super关键字访问父类的抽象方法(因为其没有具体方法体实现)

三.抽象类的特性

  1. 抽象类存在就是用来被继承的,因其不能完整描述对象,其抽象类是不能被实例化的
Shape shape = new Shape();
// 编译出错
//Error:(30, 23) java: Shape是抽象的; 无法实例化

2.抽象方法不能是 private 的

abstract class Shape {
abstract private void draw(); // 编译出错
}
//Error:(4, 27) java: 非法的修饰符组合: abstract和private

被private修饰的方法被继承后 无法被重写,而此方法是抽象的无方法体因此没有被重写没有任何意义会编译报错,而非抽象方法可以被private修饰,其有自己的方法体,可以通过调用一些公开的方法访问不会报错

  1. 抽象方法不能被final和static修饰
public abstract class Shape {
abstract final void methodA();
abstract public static void methodB();
} // 编译报错:
// Error:(20, 25) java: 非法的修饰符组合: abstract和final
// Error:(21, 33) java: 非法的修饰符组合: abstract和static

被final修饰的方法不能被重写,而抽象方法其没有方法体不被重写没有意义
被static修饰的方法是类成员方法不属于对象,不会被子类继承即不能被重写没有意义
而抽象类里可以有static和final修饰的非抽象方法,

  1. 抽象类必须被继承,并且继承后子类要重写父类中的抽象方法,否则子类也是抽象类,必须要使用 abstract 修饰
abstract class Shape{ //抽象图形类
 abstract public void draw();
}


 abstract class Triangle extends Shape {// 三角形抽象类:
@Override
public void draw() {  //重写抽象方法
System.out.println("三角形"");
} // 三角形:直角三角形、等腰三角形等,还可以继续细化

当一个抽象类被抽象类继承后即可以重写其抽象方法也可以不重写,因为其本身也是抽象的,而非抽象类继承抽象类后一定要重写抽象方法

  1. 抽象类中不一定包含抽象方法,但是有抽象方法的类一定是抽象类
  2. 抽象类中可以有构造方法,供子类创建对象时,初始化父类的成员变量

四.抽象类的作用

抽象类存在最大作用就是用来被继承的…

抽象类本身不能被实例化, 要想使用, 只能创建该抽象类的子类. 然后让子类重写抽象类中的抽象方法.

而一个普通类,其也可以被继承,内部的方法也可以被重写都具备类成员属性和方法,构造方法 ,而抽象类也就比普通类多了抽象方法,那为什么要有抽象类呢?

抽象类相比普通类来说,多了抽象这个概念,综合上面介绍的抽象类,实际上使用抽象类相当于比普通类多了一重编译器的校验.
使用抽象类其不能被实例化,其内的抽象方法不能被private static fina修饰 且一定要被非抽象的子类重写…

事实上 普通类可以作为父类被子类继承,但是在后续编写代码过程中,此父类也可以被实例化,但是其就无法在使用到任何子类的方法和行为,本身父类就是一些类共性抽取形成的一个类…

使用抽象类的场景就如上面所说, 实际工作不应该由父类完成, 而应由子类完成.
那么此时如果不小心误用成父类了, 使用普通类编译器是不会报错的. 但是父类是抽象类就会在实例化的时候提示错误, 让我们尽早发现问题.

很多语法存在的意义都是为了 “预防出错”, 例如我们曾经用过的 final 也是类似. 创建的变量用户不去修改, 不就可以相当于常量嘛?
但是加上 final 能够在不小心误修改的时候, 让编译器及时提醒我们.充分利用编译器的校验, 在实际开发中是非常有意义的.

所以在实际工作中,一个类本身就是作为父类存在,其不用被实例化,其内部的一些方法必须被重写,那么最好就设计此父类为抽象类,子类继承父类后,能够通过编译器校验提醒我们对需要重写的方法进行重写,也能避免不小心实例化的是父类对象而产生警告…

五. 抽象类实现多态

抽象类本身虽然不能实例化对象,和普通类没有很大的区别,即其类型可以创建引用变量接受子类对象地址(向上转型)

在发生向上转型后,子类重写了抽象类里的成员方法,即可以通过动态绑定实现多态
示例:

abstract class Shape{   
   
   
     void draw(){ 
        System.out.println("画图");   
    }
    String name;
    abstract  void func();   
}

class Circle extends Shape{
    @Override
    void draw(){  //可以对抽象类 有方法体的方法进行重写 也可以不重写
        System.out.println("画圆圈○");
    }
    void func(){ 
        System.out.println("实现父类的抽象方法");

    }
}

class Flower extends Shape{
    @Override
    void func(){  //即便方法体没内容也 得重写抽象方法

    }
    @Override void draw(){
        System.out.println("画花❀");
    }
}

class Rect extends Shape{   //按住ant加回车 回车 快捷出现 重写 父类的抽象方法

    @Override
    void func() {

    }
    void draw(){
        System.out.println("画矩形!");
    }
}
public class Note {
    public static void func(Shape shape){ // 在传之前已经是向上转型为shape类型 这里接受没有什么变化
        shape.draw();  //通过父类引用接受不同子类对象地址  调用其被不同子类对象重写后的方法 发生动态绑定 实现不同行为  多态
    }
    public static void main(String[] args) {
        Circle circle=new Circle();
        Shape shape=circle;
      //func实现重写了 调用的是这个子类方法
        Rect rect=new Rect();
        Flower flower=new Flower();
        Shape[] shapes={circle,rect,flower};  // shapes 为一维Shape类型数组 引用变量 每个元素是一个shape引用变量接受 子类对象地址 已经发生向上转型
        for (Shape x:shapes) {  //通过foreach 将每个转型后的地址传给方法
            func(x);
        }
    }
}

在这里插入图片描述
可见抽象类能做的,普通类都能实现,抽象类比普通类多了抽象方法且不能实例化, 在实际开发中一个类要被其他类继承最好将这个类设计为抽象类…

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue3与Vue2的区别以及Vue3的创建

Vue3带来了什么? 1.性能的提升 打包减少;初次渲染快;内存减少。 2.源码升级 使用Proxy代替defineProperty实现响应式; 重写虚拟DOM的实现和Tree-Shaking 3.使用了Typescript 4.新的特性 composition API 组合API setup配置 re…

深度学习训练营之yolov5训练自己的数据集

深度学习训练营之训练自己的数据集原文链接环境介绍准备好数据集划分数据集运行voc_train.py遇到问题完整代码创建new_data.yaml文件模型训练时遇到的报错模型训练结果可视化参考链接原文链接 🍨 本文为🔗365天深度学习训练营 中的学习记录博客&#x1f…

【专项训练】红黑树和AVL树

红黑树和AVL树 平衡二叉树: AVL Tree,and so on 如何平衡? 如何记录高度 AVL:保证任何节点的平衡因子在[-1, 0, 1] 4种旋转操作:

Linux 练习八 (IPC 信号量)

文章目录信号量介绍信号量相关函数案例一:有亲缘关系的进程使用信号量通信案例二:无亲缘关系的进程使用信号量通信使用环境:Ubuntu18.04 使用工具:VMWare workstations ,xshell作者在学习Linux的过程中对常用的命令进行…

记录--vue3+setup+ts 知识总结

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 vue3 于 2020 年 09 月 18 日正式发布,2022 年 2 月 7 日 vue3 成为新的默认版本 距离 vue3 正式发布已经过去两年有余, 成为默认版本也过去大半年了,以前还能说是对新技术、新…

SAP 凭证修改记录CDHDR / CDPOS使用及说明

目的: 一、sap的更改记录的保存 1、所有的修改记录在表CDHDR and CDPOS 2、表CDHDR 表CDHDR记录了用户于什么时间点用什么样的事务代码修改了什么样的对象 在表CDHDR字段:Change doc. Object代表了修改的对象 3、表CDPOS 是更改记录的行项目 记录…

web实现太极八卦图、旋转动画、定位、角度、坐标、html、css、JavaScript、animation

文章目录前言1、html部分2、css部分3、JavaScript部分4、微信小程序演示前言 哈哈 1、html部分 <div class"great_ultimate_eight_diagrams_box"><div class"eight_diagrams_box"><div class"eight_diagrams"><div class&…

如何使用MyBatis框架实现对数据库的增删查改?

目录&#xff1a;1.创建MyBatis项目以及如何配置2.MyBatis操作数据库的模式3.实现增删查改注意&#xff1a;在我们操作数据库之前&#xff0c;先要保证我们已经在数据库建好了一张表。创建MyBatis项目以及如何配置我们在创建项目的时候&#xff0c;引入MyBatis相关依赖配置数据…

动态内存分配之伙伴算法

伙伴算法 伙伴算法是一种在计算机内存管理中使用的算法&#xff0c;用于分配和释放内存。它是一种基于二叉树的动态内存分配算法&#xff0c;可以高效地分配和合并内存块。伙伴算法是一种按照固定大小分配内存的算法&#xff0c;例如&#xff0c;每个内存块的大小为2的n次幂&a…

MyBatis学习笔记(十二) —— MyBatis的逆向工程

12、MyBatis的逆向工程 正向工程&#xff1a;先创建Java实体类&#xff0c;由框架负责根据实体类生成数据库表。Hibernate是支持正向工程的。 逆向工程&#xff1a;先创建数据库表&#xff0c;由框架负责根据数据库表&#xff0c;反向生成如下资源&#xff1a; Java实体类Mappe…

操作系统--基于Linux的常用命令(超详细/设计/实验/作业/练习)

目录课程名&#xff1a;操作系统原理及Linux应用内容/作用&#xff1a;设计/实验/作业/练习学习&#xff1a;基于Linux的常用命令一、前言二、环境与设备三、原理四、内容五、总结与分析课程名&#xff1a;操作系统原理及Linux应用 内容/作用&#xff1a;设计/实验/作业/练习 …

苹果和富士康坚持推进印度制造,过于一厢情愿了,或加速衰退

在印度生产iPhone面临重重波折后&#xff0c;苹果和富士康仍然执意推进印度制造&#xff0c;这对于本已面临诸多风波的苹果来说并非好事&#xff0c;或许会加速苹果的衰退&#xff0c;毕竟如今的苹果早已没有当年的影响力了。一、苹果面临的问题苹果能成为智能手机市场的领导者…

【专项训练】排序算法

排序算法 非比较类的排序,基本上就是放在一个数组里面,统计每个数出现的次序 最重要的排序是比较类排序! O(nlogn)的3个排序,必须要会!即:堆排序、快速排序、归并排序! 快速排序:分治 经典快排 def quickSort1(arr

WinRAR安装教程

文章目录WinRAR安装教程无广告1. 下载2. 安装3. 注册4. 去广告WinRAR安装教程无广告 1. 下载 国内官网&#xff1a;https://www.winrar.com.cn/ 2. 安装 双击&#xff0c;使用默认路径&#xff1a; 点击“安装”。 点击“确定”。 点击“完成”。 3. 注册 链接&#xff…

第161篇 笔记-去中心化的含义

本文主要内容来自Vitalik Buterin的文章。“去中心化”这个词是在加密经济学领域用得最多的一个词&#xff0c;通常也作为辨别区块链的依据。然而&#xff0c;这个词也可能是被定义得最不恰当的一个词。数千小时的研究和价值数十亿美元哈希算力的投入都旨在实现去中心化&#x…

wsl ubuntu22.04 conda环境安装labelImg解决xcb缺失问题

labelImg 安装 pip install PyQt5 -i https://pypi.tuna.tsinghua.edu.cn/simple/ pip install pyqt5-tools -i https://pypi.tuna.tsinghua.edu.cn/simple/ pip install lxml -i https://pypi.tuna.tsinghua.edu.cn/simple/ pip install labelImg -i https://pypi.tuna.tsingh…

Java基础学习(2)

Java基础学习一 基础概念1.1 注释1.2 关键字1.3 字面量特殊字符1.4 变量1.5 数据类型1.6 标识符1.7 键盘输入二 运算符隐式转换强制转换三元运算符运算符的优先级二 源码 补码 反码2.1 源码2.2 反码2.3 补码其他运算符逻辑与逻辑或左移右移一 基础概念 1.1 注释 对自己所写的内…

HTML快速入门

目录HTML概念HTML基本格式基本语法常用标签1.文件标签&#xff1a;构成html最基本的标签2.文本标签&#xff1a;和文本有关的标签3.列表标签4.图片标签5.超链接标签6.表格标签7.表单标签HTML概念 HTML是最基础的网页开发语言&#xff0c;Hyper Text Markup Language&#xff0…

保姆级使用PyTorch训练与评估自己的Replknet网络教程

文章目录前言0. 环境搭建&快速开始1. 数据集制作1.1 标签文件制作1.2 数据集划分1.3 数据集信息文件制作2. 修改参数文件3. 训练4. 评估5. 其他教程前言 项目地址&#xff1a;https://github.com/Fafa-DL/Awesome-Backbones 操作教程&#xff1a;https://www.bilibili.co…

cocoscreator打包android app bundle使用Play Asset Delivery分包

1.cocoscreator构建完android项目 2.用androidstudio打开项目 3.点击androidstudio上项目目录左上角的Android改为Project 4. 在项目目录下新建Modul 5.选择Android Library 6.命名assetPack1或者自定义&#xff0c;点击Finish 7.在新建的assetPack1目录下找到build.gradle并…