当前位置: 首页 > article >正文

抽象类与抽象方法详解

目录

一、 基本概念

1.抽象类(Abstract Class):

2.抽象方法(Abstract Method):

二、示例代码

抽象类

抽象方法

三、抽象类的使用场景

四、 抽象类与接口的对比

五、注意事项

六、总结


一、 基本概念

1.抽象类(Abstract Class):

定义:抽象类是用 abstract 关键字修饰的类。抽象类不能被实例化,只能通过子类继承来使用。它可以包含抽象方法(无实现)和具体方法(有实现)。它的主要目的是为子类提供一个通用的模板和结构。
特点:
抽象类中可以包含普通方法(有实现的方法)和抽象方法(没有实现的方法)。
抽象类中可以有成员变量、构造方法、静态方法和非静态方法。
抽象类的一个重要用途是提供一个统一的接口,强制子类实现某些方法。

①不可实例化:由于抽象类可能包含未实现的抽象方法,因此不能直接创建其实例。
②构造器存在:尽管抽象类不能被实例化,但它仍然可以拥有构造器,用于初始化其子类对象时调用。
③部分实现:抽象类可以包含具体的实现代码,这意味着它可以提供一些默认的行为给子类使用。
④强制性继承:任何继承自抽象类的非抽象子类都必须实现该抽象类中的所有抽象方法,除非这个子类也是抽象的。

2.抽象方法(Abstract Method):

定义:

abstract 关键字修饰的方法,没有方法体(即没有 { } 包裹的实现代码),必须在子类中被重写(Override)。
特点:
抽象方法必须定义在抽象类中,普通类不能包含抽象方法。
抽象方法的目的是为子类提供一个统一的接口,子类必须重写这些方法。
如果一个子类继承了包含抽象方法的抽象类,但没有重写所有的抽象方法,那么子类也必须声明为抽象类。

①无方法体:抽象方法只包含方法声明,不包含方法的具体实现。
②强制重写:如果一个类包含了抽象方法,则这个类也必须声明为抽象类;任何继承此类的非抽象子类都必须提供抽象方法的具体实现。


二、示例代码

抽象类

  • 定义方式

    public abstract class Animal { 
        // 抽象方法
        public abstract void makeSound();
        
        // 具体方法
        public void sleep() {
            System.out.println("动物在睡觉");
        }
    }
  • 核心规则

    1. 抽象类中可以有普通成员变量、具体方法、构造方法、静态方法。

    2. 包含抽象方法的类必须是抽象类,但抽象类可以不包含抽象方法。

    3. 子类继承抽象类后,必须实现所有抽象方法,否则子类也必须声明为抽象类。


抽象方法

  • 定义方式

    public abstract void eat(); // 没有方法体,以分号结尾
  • 核心规则

    1. 抽象方法只能存在于抽象类中。

    2. 子类必须重写抽象方法,否则会编译报错。

    3. 抽象方法不能是 privatestatic 或 final 的(这些修饰符与继承和多态冲突)

三、抽象类的使用场景

  • 模板方法模式:定义算法的骨架,将某些步骤延迟到子类实现。

    抽象类Game
    
    public abstract class Game {
        // 模板方法(定义流程)
        public final void play() {
            initialize();
            start();
            end();
        }
        
        // 抽象方法(子类必须实现)
        protected abstract void initialize();
        protected abstract void start();
        
        // 具体方法(公共逻辑)
        private void end() {
            System.out.println("游戏结束");
        }
    }
    子类Chess
    
    class Chess extends Game {
        @Override
        protected void initialize() { System.out.println("初始化棋盘"); }
        @Override
        protected void start() { System.out.println("开始下棋"); }
    }
     
  • 公共代码复用:多个子类共享某些方法的实现。

    抽象类Vehicle:
    
    public abstract class Vehicle {
        // 公共属性
        private String brand;
        
        // 公共方法
        public void startEngine() {
            System.out.println("引擎启动");
        }
        
        // 抽象方法(子类自定义)
        public abstract void drive();
    }
    子类Car:
    
    class Car extends Vehicle {
        @Override
        public void drive() { System.out.println("汽车行驶"); }
    }

四、 抽象类与接口的对比

以下是修正后的对比表格,结合Java最新特性(至Java 17)和设计语义优化:

特性抽象类接口
继承/实现方式单继承(extends)多实现(implements)
方法类型可包含:
- 抽象方法
- 具体方法(默认实现)
可包含:
- 抽象方法
- 默认方法(default
- 静态方法(static
- 私有方法(Java 9+)
成员变量可包含:
- 普通成员变量
- 常量
仅允许常量:
默认隐式 public static final
构造方法可以有构造方法(用于子类初始化)不能有构造方法
访问修饰符方法/变量可自定义访问修饰符(如 protected方法默认 public(不可用 private/protected
设计语义定义类的本质特征(is-a关系)
例:DogAnimal
定义能力契约(can-do关系)
例:Serializable表示可序列化能力
典型用途封装通用逻辑和状态(模板方法模式)定义跨类别的行为约定(策略模式)
Java版本演进核心特性自Java 1.0未变逐步增强:

适用场景

  • 抽象类:多个子类有共享的代码逻辑或属性时(如 Animal 作为基类)。

  • 接口:定义不相关类的共同行为(如 FlyableSwimmable)。


五、注意事项

  1. 抽象类的构造方法
    抽象类可以有构造方法,但只能被其子类调用。

    抽象类Animal:
    
    abstract class Animal {
        public Animal(String name) { /* 初始化逻辑 */ }
    }
    子类Dog:
    
    class Dog extends Animal {
        public Dog() { super("狗"); }
    }
  2. 静态方法的使用
    抽象类中可以定义静态方法,但静态方法不能被重写。

    abstract class Logger {
        public static void log(String message) {
            System.out.println("[LOG] " + message);
        }
    }
    
    class FileLogger extends Logger {
        // 不能重写log方法,但可以直接调用Logger.log()
    }
  3. 避免过度抽象
    只有需要强制子类实现特定行为时,才使用抽象方法。不要为未明确的需求提前设计抽象。


六、总结

  • 抽象类:提供代码复用和模板设计,适合定义类族(如动物、车辆)的公共逻辑。

  • 抽象方法:强制子类实现特定行为,确保多态的正确性。

  • 与接口的区别:抽象类强调“是什么”,接口强调“能做什么”。

核心价值
通过抽象类与抽象方法,可以构建灵活、可扩展的代码结构,符合面向对象设计的开闭原则(OCP)——对扩展开放,对修改关闭。


http://www.kler.cn/a/527833.html

相关文章:

  • 侯捷 C++ 课程学习笔记:深入理解 C++ 核心技术与实战应用
  • FreeRTOS从入门到精通 第十五章(事件标志组)
  • DeepSeek介绍
  • maven、npm、pip、yum官方镜像修改文档
  • 快速提升网站收录:避免常见SEO误区
  • ResNet 残差网络
  • Matrials studio 软件安装步骤(百度网盘链接)
  • 【RocketMQ 存储】- broker 端存储批量消息的逻辑
  • CE-PBFT:大规模联盟区块链的高可用一致性算法
  • Unet 改进:在encoder和decoder间加入TransformerBlock
  • 【leetcode强化练习·二叉树】同时运用两种思维解题
  • 【Java异步编程】CompletableFuture基础(1):创建不同线程的子任务、子任务链式调用与异常处理
  • 黑马点评 - 商铺类型缓存练习题(Redis List实现)
  • Hive:复杂数据类型之Map函数
  • 深度学习之“数据的相关性”
  • 人工智能导论--第1章-知识点与学习笔记
  • 用一个例子详细说明python单例模式
  • 【AI论文】VideoAuteur:迈向长叙事视频
  • gentoo linux中安装希沃白板5
  • Docker技术简介
  • Longformer:处理长文档的Transformer模型
  • 6.二分算法
  • 舵机型号与识别
  • Go学习:Go语言中if、switch、for语句与其他编程语言中相应语句的格式区别
  • 三天急速通关JavaWeb基础知识:Day 2 前端基础知识(计划有变,前端工程化部分暂时搁置)
  • Vue.js 生命周期钩子在 Composition API 中的应用