Java抽象类

Java中的抽象类(Abstract Class)是一种特殊类型的类,它无法被实例化,只能被用作其他类的基础。抽象类用于定义具有共同特征和行为的一组相关类的共同结构和方法。抽象类可以包含抽象方法(没有具体实现的方法)和具体方法(有实际实现的方法)。

文章目录

    • 抽象类_abstract,不可被实例化:
      • 格式:
      • 但是可以创建抽象类的对象变量(object variable),但是这样一个变量只能引用子类的对象。
          • 好处:类似与方法重载,能够使用其特定的方法
    • 抽象方法_abstract,不可被实例化 ,子类必须实现
    • 抽象类的主要特点包括:
    • 6. 可以有构造方法: 这些构造方法在子类实例化时可以被调用【给子类对象赋值】,通常用于初始化抽象类中的字段。
    • 7.抽象类的子类要么重写抽象类中的所有抽象方法要么是抽象类:
      • 详细地讨论一下。
      • 举例子;

抽象类_abstract,不可被实例化:

作为他类的基类,用于定义共同的特征和行为,抽象类中的抽象方法未明确具体的方法
尽量将字段和方法(不论是否为抽象类)放在超类(不论是否是abstract)中

父类具有的是一般性,也可能抽象。
但从某种角度来说,其作为派生其他类的基类,而不是用到自己的想要的方式的特点实例。

如:

		Person
	       |
  ——————————————————————————————
  |								|
  Employee				Student

格式:

[修饰符]abstract class ClassName [extends 父类] [implements 接口列表]{
	成员内容}

但是可以创建抽象类的对象变量(object variable),但是这样一个变量只能引用子类的对象。

Person p =new Student();

p是抽象类型Person的一个变量,引用了非抽象子类Student的一个实例。

在这里插入图片描述
其中三角形和长方形的类中的实现了面积的方法是具体的,不再是抽象类了

好处:类似与方法重载,能够使用其特定的方法

抽象类可以用作一个通用的基类,它定义了一组通用的属性和方法。然后,具体的子类可以继承这个抽象类,并根据具体的需求来实现或扩展其中的方法。这种结构允许你在处理多个不同的子类时,使用抽象类类型的引用,从而获得多态性和灵活性的好处。
在这里插入图片描述

抽象方法_abstract,不可被实例化 ,子类必须实现

==其相当于子类实现本体的具体的方法的**占位符**==。
[修饰符]abstract 返回类型 方法名 ([参数列表][throws 异常列表]

抽象方法没有方法体,直接 分号;结束
含有抽象方法的类必须是抽象类,不能被实例化
抽象方法必须在子类中实现

如果抽象类中没有抽象方法,在子类在定义方法。就不能用父类引用子类中新增的内容了(和多态中类似,方法表

扩展抽象类:
(1)保留抽象类的部分或者所有抽象方法仍未定义,这样子类也必须标记为抽象类;

// 抽象类
abstract class Animal {
    abstract void makeSound();  // 抽象方法
}

// 抽象子类,因为没有实现抽象方法
abstract class Bird extends Animal {
    // 这里没有提供对抽象方法 makeSound 的实现
}

// 具体子类,实现了抽象方法,可以被实例化
class Dog extends Animal {
    @Override
    void makeSound() {
        System.out.println("Dog barks");
    }
}

// 具体子类,实现了抽象方法,可以被实例化
class Cat extends Animal {
    @Override
    void makeSound() {
        System.out.println("Cat meows");
    }
}

Bird 是一个抽象子类,因为它继承了抽象父类 Animal,但没有提供对抽象方法 makeSound 的实现。而 Dog 和 Cat 都是具体子类,它们实现了抽象方法 makeSound,因此可以被实例化。

(2)定义全部方法,子类就不会抽象了。

// 抽象类
abstract class Shape {
    abstract double calculateArea();  // 抽象方法

    double calculatePerimeter() {
        return 0;  // 这里只是示范,具体计算逻辑需要实现类提供
    }
}

// 具体子类,实现了抽象方法,可以被实例化
class Circle extends Shape {
    double radius;

    Circle(double radius) {
        this.radius = radius;
    }

    @Override
    double calculateArea() {
        return Math.PI * radius * radius;
    }

    @Override
    double calculatePerimeter() {
        return 2 * Math.PI * radius;
    }
}

// 具体子类,实现了抽象方法,可以被实例化
class Rectangle extends Shape {
    double width;
    double height;

    Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    @Override
    double calculateArea() {
        return width * height;
    }

    @Override
    double calculatePerimeter() {
        return 2 * (width + height);
    }
}

在这里插入图片描述

抽象类的主要特点包括:

强制子类必须按照特定的格式进行方法重写
抽象方法所在的类就是抽象类
  1. 不能被实例化:不能使用new关键字直接创建抽象类的实例。

  2. 可以包含抽象方法:抽象类可以定义抽象方法,这些方法没有实际的代码实现,只有方法签名。子类必须实现抽象类中的所有抽象方法。

     如果一个类包含至少一个抽象方法,那么这个类必须声明为抽象类。
    
  3. 可以包含具体方法:抽象类也可以包含具体的方法实现,这些方法在抽象类中有默认的实现,子类可以选择性地覆盖这些方法。

  4. 用于继承:其他类可以继承抽象类,并通过实现抽象方法来提供具体的实现。子类继承了抽象类的属性和方法。

  5. 用于多态:抽象类可以用于实现多态性,通过父类引用指向子类对象。

6. 可以有构造方法: 这些构造方法在子类实例化时可以被调用【给子类对象赋值】,通常用于初始化抽象类中的字段。

虽然抽象类本身不能被实例化,但是抽象类的构造方法仍然有其用途。抽象类的构造方法在以下几种情况下是有用的:

  1. 初始化抽象类的字段: 抽象类可以包含字段(成员变量),这些字段可以在构造方法中进行初始化。子类在实例化时会调用父类的构造方法来初始化父类的字段。

  2. 在子类构造方法中调用: 当子类实例化时,它的构造方法会隐式或显式地调用父类的构造方法,以确保父类的初始化逻辑得以执行。

  3. 构造方法的继承: 子类继承了父类的构造方法,尽管不能直接实例化抽象类,但子类在实例化时仍然需要调用适当的构造方法,以初始化继承自父类的字段。

  4. 调用抽象类中的方法: 构造方法也可以用于调用抽象类中的其他方法,无论这些方法是抽象的还是具体的。这些方法可能在子类的构造方法中执行特定的初始化逻辑。

尽管抽象类本身不能被实例化,但构造方法在创建其子类的对象时扮演着关键的角色。子类的构造方法在执行时会先调用父类的构造方法,以确保继承链中的初始化步骤得以完成。这有助于保持继承关系中的数据完整性和一致性。

7.抽象类的子类要么重写抽象类中的所有抽象方法要么是抽象类:

如果一个类继承了一个抽象类,并且不是抽象类本身,那么它要么必须提供实现来覆盖抽象类中的所有抽象方法,要么就必须自己声明为抽象类。如果子类没有提供实现,那么它也必须声明为抽象类。

以下是一个简单的Java抽象类的示例:

abstract class Animal {
    String name;

    Animal(String name) {
        this.name = name;
    }

    abstract void makeSound(); // 抽象方法,子类必须实现

    void eat() {
        System.out.println(name + " is eating."); // 具体方法
    }
}

class Dog extends Animal {
    Dog(String name) {
        super(name);
    }

    void makeSound() {
        System.out.println(name + " barks.");
    }
}

class Cat extends Animal {
    Cat(String name) {
        super(name);
    }

    void makeSound() {
        System.out.println(name + " meows.");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog("Buddy");
        Cat cat = new Cat("Whiskers");

        dog.makeSound();
        cat.makeSound();

        dog.eat();
        cat.eat();
    }
}

在这个示例中,Animal是一个抽象类,它定义了一个抽象方法makeSound()和一个具体方法eat()DogCatAnimal的子类,它们必须实现makeSound()方法。在Main类中,通过多态性调用不同子类的方法。

抽象类的子类在继承抽象类时,通常必须实现抽象类中的所有抽象方法。抽象类是一种不能被实例化的类,它可以包含普通的方法和属性,也可以包含抽象方法。抽象方法是在抽象类中声明但没有提供具体实现的方法,它相当于一种约定,要求子类必须提供具体的实现。
······
当一个类继承一个抽象类时,如果该子类本身不是抽象类,那么它必须提供实现抽象类中所有抽象方法的具体实现。如果子类没有实现抽象类中的全部抽象方法,那么这个子类也必须被声明为抽象类。
·······
在面向对象编程中,抽象类和抽象方法用于定义一个通用的接口或者约定,以便子类可以继承并提供具体的实现。这种机制能够强制子类按照预期的方式来实现方法,从而保证代码的一致性和可维护性。

详细地讨论一下。

  1. 抽象方法(Abstract Methods): 抽象方法是在抽象类中声明的方法,它没有具体的实现代码,只有方法签名。子类必须实现抽象类中的抽象方法。这适用于在不同的子类中有不同的实现,而且你希望强制子类提供自己的实现。抽象方法通常用于定义基本操作,但这些操作在不同的子类中可能有不同的行为。

  2. 成员方法(Concrete Methods): 成员方法是在抽象类中有具体实现的方法。这些方法可以在抽象类中提供通用的、共享的实现,以避免在每个子类中重复编写相同的代码。子类可以选择性地覆盖这些方法,以适应特定的需求。成员方法通常用于实现通用的功能,这些功能在多个子类中都可以共享。

总之,你可以这样理解:

  • 使用抽象方法:当你希望在不同的子类中有不同的实现,而且这些实现在子类中是必需的时,你应该使用抽象方法。抽象方法强制子类提供自己的实现,确保基类的方法在子类中被正确覆盖。

  • 使用成员方法:当你有一些通用的、可复用的代码实现,可以在抽象类中提供默认的具体实现。子类可以直接继承这些方法,避免重复编写相同的代码。子类也可以选择性地覆盖这些方法,以适应特定需求。

需要注意的是,抽象类可以同时包含抽象方法和成员方法,这取决于你的设计需求。通过合理地使用抽象方法和成员方法,可以在代码中实现良好的组织和重用。

举例子;

package oop_useAbstractClass;

// 定义一个抽象类 Shape,用于表示各种几何图形
public abstract class Shape {
    public int width; // 用于存储几何图形的宽度
    public int height; // 用于存储几何图形的高度

    // 构造方法,用于初始化宽度和高度
    public Shape(int width, int height) {
        this.width = width;
        this.height = height;
    }

    // 声明一个抽象方法 area(),用于计算图形的面积
    public abstract double calculateArea();
}

package oop_useAbstractClass;

// 长方形类,继承自抽象类 Shape
public class Rectangle extends Shape {
    // 构造函数,接受长方形的长度和宽度作为参数
    public Rectangle(int length, int width) {
        // 调用父类的构造函数来初始化长度和宽度
        super(length, width);
    }

    // 重写父类中的抽象方法,计算长方形的面积
    @Override
    public double calculateArea() {
        // 长方形的面积计算公式:长度 * 宽度
        return width * height;
    }
}

package oop_useAbstractClass;

public class Triangle extends Shape {
    public Triangle(int width, int height) {
        super(width, height);
    }

    // 重写父类中的抽象方法,计算三角形面积的功能
    @Override
    public double calculateArea() {
        return 0.5 * width * height;
    }
}

package oop_useAbstractClass;


public class ShapeTest {
    public static void main(String[] args) {
        // 创建一个长方形对象并初始化其长和宽
        Rectangle rectangle = new Rectangle(5, 4);
        // 计算并输出长方形的面积
        System.out.println("长方形的面积为:" + rectangle.calculateArea());

        // 创建一个三角形对象并初始化其底边和高
        Triangle triangle = new Triangle(2, 5);
        // 计算并输出三角形的面积
        System.out.println("三角形的面积为:" + triangle.calculateArea());
    }
}

在这里插入图片描述

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

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

相关文章

常见前端面试之VUE面试题汇总二

4. slot 是什么?有什么作用?原理是什么? slot 又名插槽,是 Vue 的内容分发机制,组件内部的模板引擎使用 slot 元素作为承载分发内容的出口。插槽 slot 是子组件的一个模板 标签元素,而这一个标签元素是否显…

学习JAVA打卡第四十天

对象的字符串表示 在此类中我们讲过,所有的类都默认是java.lang包中object类的子类或间接子类。 Object类有一个public String toString()方法,一个对象通过调用该方法可以获得该对象的字符串表示。一个对象调用toString法(&…

U盘怎么加密?U盘加密方法有哪些?

U盘是我们生活和工作中最常用的移动储存设备,经常被用来存放各种重要数据,为了保证数据的安全,我们需要加密U盘。那么,U盘加密方法有哪些呢? U盘加密普通方法 如果你的U盘储存数据不多,并且对于加密的要求…

回归预测 | MATLAB实现PSO-RF粒子群优化算法优化随机森林算法多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现PSO-RF粒子群优化算法优化随机森林算法多输入单输出回归预测(多指标,多图) 目录 回归预测 | MATLAB实现PSO-RF粒子群优化算法优化随机森林算法多输入单输出回归预测(多指标,多图)效果…

数据结构入门 — 链表详解_双向链表

前言 数据结构入门 — 双向链表详解* 博客主页链接:https://blog.csdn.net/m0_74014525 关注博主,后期持续更新系列文章 文章末尾有源码 *****感谢观看,希望对你有所帮助***** 系列文章 第一篇:数据结构入门 — 链表详解_单链表…

OSCS开源安全周报第 56 期:Apache Airflow Spark Provider 任意文件读取漏洞

本周安全态势综述 OSCS 社区共收录安全漏洞 3 个,公开漏洞值得关注的是 Apache NiFi 连接 URL 验证绕过漏洞(CVE-2023-40037)、PowerJob 未授权访问漏洞(CVE-2023-36106)、Apache Airflow Spark Provider 任意文件读取漏洞(CVE-2023-40272)。 针对 NPM 、PyPI 仓库…

4.9 已建立连接的TCP,收到SYN会发生什么?

1. 客户端的 SYN 报文里的端口号与历史连接不相同 此时服务端会认为是新的连接要建立,于是就会通过三次握手来建立新的连接。 旧连接里处于 Established 状态的服务端最后会怎么样呢? 服务端给客户端发消息了:客户端连接已被关闭&#xff…

C++信息学奥赛1138:将字符串中的小写字母转换成大写字母

#include<bits/stdc.h> using namespace std; int main() {string arr;// 输入一行字符串getline(cin, arr);for(int i0;i<arr.length();i){if(arr[i]>97 and arr[i]<122){char aarr[i]-32; // 将小写字母转换为大写字母cout<<a; // 输出转换后的字符}els…

操作系统-笔记-第二章-锁

&#x1f338;章节汇总 一、第一章——操作系统的概念 二、第二章——【进程】 二、第二章——【线程】​编辑 二、第二章——【进程调度】 二、第二章——【进程同步与互斥】 二、第二章——【锁】 三、第三章——内存管理 四、第四章——文件管理 五、第五章——输入输出管理…

学习笔记|认识蜂鸣器|控制原理|电磁炉LED实战|逻辑运算|STC32G单片机视频开发教程(冲哥)|第八集(上):蜂鸣器应用

文章目录 1.认识蜂鸣器区别 2.控制原理实现蜂鸣器控制原理 3.蜂鸣器实战应用需求分析代码编写步骤一代码编写及分析test.h的固定模板Tips:提示&#xff1a;“test\test.c(14): error C16: unprintable character 0xA3 skippedTips&#xff1a;“test\test.c(14): warning C137:…

R语言如果列表中有列表,且每个子列表有一个向量:如何转变为仅仅一个列表里面含有向量

引言 有些时候&#xff0c;比如批量读取表格中的某一列的时候&#xff0c;最终你会得到列表里面装列表&#xff0c;且每个列表里面只有一个向量的情况。我们的目标是不要中间这一层列表&#xff0c;而是直接变成列表-向量这种简单的结构&#xff0c;如何完成呢。我觉得有很多方…

Linux Ubuntu系统安装OpenVPN服务

OpenVPN Ubuntu/Linux 服务端安装 官方文档&#xff1a;https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage 介绍 嘿&#xff0c;今天我们要探讨的话题是OpenVPN——那个让你在互联网上以安全又私密的方式冲浪的神奇工具。 首先&#xff0c;你可能会问&#xff…

用正则处理Unicode 编码的文本

Unicode&#xff08;中文&#xff1a;万国码、国际码、统一码、单一码&#xff09;是计算机科学领域里的一项业界标准。它对世界上大部分的文字进行了整理、编码。Unicode 使计算机呈现和处理文字变得简单。 现在的 Unicode 字符分为 17 组编排&#xff0c;每组为一个平面&…

什么是住宅ip,静态和动态怎么选?

上文我们介绍了数据中心代理&#xff0c;这次我们来介绍下住宅代理ip&#xff0c;住宅代理ip分类两种类型&#xff1a;静态住宅代理和动态住宅代理&#xff0c;他们有什么区别又能用在什么场景呢&#xff1f;我们先从他们是如何运作开始。 一、什么是住宅代理ip isp住宅代理i…

C++内存模型

目录 内存模型分类 堆和栈的区别 C中new的工作过程 堆和栈的区别 为什么堆区要比栈区大 内存模型分类 文本段&#xff08;ELF&#xff09;&#xff08;数据区&#xff09;&#xff1a;主要用于存放我们编写的代码&#xff0c;但是不是按照代码文本的形式存放&#xff0c;而…

打开软件提示msvcp140.dll丢失的解决方法,msvcp140主要丢失原因

今天&#xff0c;我将为大家介绍一种非常常见的问题——msvcp140.dll丢失。这个问题可能会导致许多应用程序无法正常运行&#xff0c;甚至崩溃。但是&#xff0c;请不要担心&#xff0c;我会为大家提供5种解决方法&#xff0c;帮助大家轻松解决问题。 首先&#xff0c;我们来看…

分布式搜索引擎----elasticsearch

目录 1、初识elasticsearch 1.1、什么是elasticsearch 1.2.ELK技术栈 2、正向索引和倒排索引 2.1、正向索引 2.2、倒排索引 2.3、正向索引和倒排索引的区别 3、elasticsearch中的概念理解 3.1、文档和字段 3.2、索引和映射 3.3、mysql与elasticsearch 1、初识elasti…

【C++11】future和async等

C11的future和async等关键字 1.async和future的概念 std::async 和 std::future 是 C11 引入的标准库功能&#xff0c;用于实现异步编程&#xff0c;使得在多线程环境中更容易处理并行任务。它们可以帮助你在不同线程中执行函数&#xff0c;并且能够方便地获取函数的结果。 在…

Spring Boot(Vue3+ElementPlus+Axios+MyBatisPlus+Spring Boot 前后端分离)【二】

&#x1f600;前言 本篇博文是关于Spring Boot(Vue3ElementPlusAxiosMyBatisPlusSpring Boot 前后端分离)【二】的&#xff0c;希望你能够喜欢 &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文…

命令全局安装 ts

1.全局安装 typeScript编译 npm install -g typescript2.查看版本 tsc-v安装成功的画面
最新文章