ABAP核心进阶篇(120篇):继承、多态与接口(12篇)
第七篇:接口 vs 抽象类:ABAP OOP两类扩展方式的差异与选型原则
博客标题:《接口 vs 抽象类:ABAP OOP两类扩展方式的差异与选型原则》
博客简介:系统对比接口与抽象类的语法特性、适用场景差异,结合"多能力实现"与"层级模板复用"两类典型业务需求,给出明确的选型判断标准,梳理混淆接口与抽象类使用的常见设计失误与优化方案。
📖 写在前面
在ABAP面向对象编程中,接口(Interface) 和 抽象类(Abstract Class) 是实现代码扩展和多态的两种核心方式。很多开发者在实际项目中容易混淆这两种方式的适用场景,导致设计不合理、代码难以维护。
核心区别:
#mermaid-svg-VpDdfjDpPJ2E71fN{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-VpDdfjDpPJ2E71fN .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-VpDdfjDpPJ2E71fN .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-VpDdfjDpPJ2E71fN .error-icon{fill:#552222;}#mermaid-svg-VpDdfjDpPJ2E71fN .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-VpDdfjDpPJ2E71fN .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-VpDdfjDpPJ2E71fN .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-VpDdfjDpPJ2E71fN .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-VpDdfjDpPJ2E71fN .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-VpDdfjDpPJ2E71fN .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-VpDdfjDpPJ2E71fN .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-VpDdfjDpPJ2E71fN .marker{fill:#333333;stroke:#333333;}#mermaid-svg-VpDdfjDpPJ2E71fN .marker.cross{stroke:#333333;}#mermaid-svg-VpDdfjDpPJ2E71fN svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-VpDdfjDpPJ2E71fN p{margin:0;}#mermaid-svg-VpDdfjDpPJ2E71fN .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-VpDdfjDpPJ2E71fN .cluster-label text{fill:#333;}#mermaid-svg-VpDdfjDpPJ2E71fN .cluster-label span{color:#333;}#mermaid-svg-VpDdfjDpPJ2E71fN .cluster-label span p{background-color:transparent;}#mermaid-svg-VpDdfjDpPJ2E71fN .label text,#mermaid-svg-VpDdfjDpPJ2E71fN span{fill:#333;color:#333;}#mermaid-svg-VpDdfjDpPJ2E71fN .node rect,#mermaid-svg-VpDdfjDpPJ2E71fN .node circle,#mermaid-svg-VpDdfjDpPJ2E71fN .node ellipse,#mermaid-svg-VpDdfjDpPJ2E71fN .node polygon,#mermaid-svg-VpDdfjDpPJ2E71fN .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-VpDdfjDpPJ2E71fN .rough-node .label text,#mermaid-svg-VpDdfjDpPJ2E71fN .node .label text,#mermaid-svg-VpDdfjDpPJ2E71fN .image-shape .label,#mermaid-svg-VpDdfjDpPJ2E71fN .icon-shape .label{text-anchor:middle;}#mermaid-svg-VpDdfjDpPJ2E71fN .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-VpDdfjDpPJ2E71fN .rough-node .label,#mermaid-svg-VpDdfjDpPJ2E71fN .node .label,#mermaid-svg-VpDdfjDpPJ2E71fN .image-shape .label,#mermaid-svg-VpDdfjDpPJ2E71fN .icon-shape .label{text-align:center;}#mermaid-svg-VpDdfjDpPJ2E71fN .node.clickable{cursor:pointer;}#mermaid-svg-VpDdfjDpPJ2E71fN .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-VpDdfjDpPJ2E71fN .arrowheadPath{fill:#333333;}#mermaid-svg-VpDdfjDpPJ2E71fN .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-VpDdfjDpPJ2E71fN .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-VpDdfjDpPJ2E71fN .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VpDdfjDpPJ2E71fN .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-VpDdfjDpPJ2E71fN .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VpDdfjDpPJ2E71fN .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-VpDdfjDpPJ2E71fN .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-VpDdfjDpPJ2E71fN .cluster text{fill:#333;}#mermaid-svg-VpDdfjDpPJ2E71fN .cluster span{color:#333;}#mermaid-svg-VpDdfjDpPJ2E71fN div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-VpDdfjDpPJ2E71fN .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-VpDdfjDpPJ2E71fN rect.text{fill:none;stroke-width:0;}#mermaid-svg-VpDdfjDpPJ2E71fN .icon-shape,#mermaid-svg-VpDdfjDpPJ2E71fN .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VpDdfjDpPJ2E71fN .icon-shape p,#mermaid-svg-VpDdfjDpPJ2E71fN .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-VpDdfjDpPJ2E71fN .icon-shape .label rect,#mermaid-svg-VpDdfjDpPJ2E71fN .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VpDdfjDpPJ2E71fN .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-VpDdfjDpPJ2E71fN .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-VpDdfjDpPJ2E71fN :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 面向对象扩展方式
接口
抽象类
定义'做什么'
(行为契约)
多重实现
能力组合
定义'怎么做'
(模板骨架)
单继承
代码复用
💡 一句话总结:
- 接口:定义"做什么"(What)------ 行为契约
- 抽象类:定义"怎么做"(How)------ 模板骨架
本文将系统对比两者的语法特性、适用场景差异,给出明确的选型判断标准,并通过实际案例解析常见的设计失误与优化方案。
一、核心概念回顾
1.1 接口(Interface)
定义:接口是一种只声明方法签名、不提供具体实现的抽象类型。它定义了一组行为契约,由实现类来兑现。
| 特点 | 说明 |
|---|---|
| 🔹 只声明不实现 | 所有方法只有签名,没有代码体 |
| 🔹 成员全公开 | 所有成员默认为 PUBLIC |
| 🔹 多重实现 | 一个类可以实现多个接口 |
| 🔹 仅常量和类型 | 不能包含变量(DATA),只能包含常量(CONSTANTS)和类型(TYPES) |
| 🔹 不可实例化 | 不能直接创建对象 |
代码示例:
abap
" ================================================================
" 接口定义
" ================================================================
INTERFACE zif_settlement
PUBLIC.
CONSTANTS: gc_success TYPE char1 VALUE 'S'.
TYPES: BEGIN OF ty_order,
order_id TYPE ebeln,
amount TYPE netwr,
vendor TYPE lifnr,
END OF ty_order.
METHODS: settle
IMPORTING
is_order TYPE ty_order
RETURNING
VALUE(rv_success) TYPE abap_bool.
METHODS: validate
IMPORTING
is_order TYPE ty_order
RETURNING
VALUE(rv_valid) TYPE abap_bool.
ENDINTERFACE.
1.2 抽象类(Abstract Class)
定义:抽象类是包含抽象方法(未实现)和具体方法(已实现)的类。它不能被实例化,但可以为子类提供模板和默认实现。
| 特点 | 说明 |
|---|---|
| 🔶 含抽象方法 | 至少包含一个抽象方法(无实现) |
| 🔶 也有具体方法 | 可包含已实现的具体方法,供子类复用 |
| 🔶 可含属性 | 支持完整的属性(DATA)、常量、类型 |
| 🔶 单继承 | 一个类只能继承一个抽象类 |
| 🔶 不可实例化 | 不能直接创建对象,需通过子类实例化 |
代码示例:
abap
" ================================================================
" 抽象类定义
" ================================================================
CLASS zcl_settlement DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS: settle ABSTRACT. " 抽象方法(无实现)
CONSTANTS: gc_success TYPE char1 VALUE 'S'.
PROTECTED SECTION.
DATA: amount TYPE netwr. " 可包含属性
METHODS: validate_order. " 具体方法(有实现)
ENDCLASS.
CLASS zcl_settlement IMPLEMENTATION.
METHOD validate_order.
" ✅ 具体实现代码
IF amount <= 0.
WRITE: / '金额无效'.
ENDIF.
ENDMETHOD.
ENDCLASS.
二、全方位对比
2.1 核心语法对比表
| 维度 | 接口(Interface) | 抽象类(Abstract Class) |
|---|---|---|
| 定义关键字 | INTERFACE |
CLASS ... DEFINITION ABSTRACT |
| 方法实现 | ❌ 只声明,不实现 | ✅ 可含抽象方法 + 具体方法 |
| 成员可见性 | 全部为 PUBLIC |
支持 PUBLIC/PROTECTED/PRIVATE |
| 属性支持 | ❌ 仅常量和类型 | ✅ 完整属性支持 |
| 继承方式 | 类实现接口(INTERFACES) |
类继承类(INHERITING FROM) |
| 多重实现 | ✅ 可实现多个 | ❌ 只能单继承 |
| 实例化 | ❌ 不可实例化 | ❌ 不可实例化 |
| 方法调用 | 接口名~方法名 |
直接调用或 SUPER->方法名 |
2.2 代码实现方式对比
abap
" ================================================================
" 🔷 类实现接口
" ================================================================
CLASS zcl_standard_settlement DEFINITION.
PUBLIC SECTION.
INTERFACES: zif_settlement. " 实现接口
ENDCLASS.
CLASS zcl_standard_settlement IMPLEMENTATION.
METHOD zif_settlement~settle. " 方法名格式
" 实现逻辑
ENDMETHOD.
ENDCLASS.
" ================================================================
" 🔶 类继承抽象类
" ================================================================
CLASS zcl_standard_settlement DEFINITION
INHERITING FROM zcl_settlement. " 继承抽象类
PUBLIC SECTION.
METHODS: settle REDEFINITION. " 重写抽象方法
ENDCLASS.
CLASS zcl_standard_settlement IMPLEMENTATION.
METHOD settle.
super->validate_order( ). " 调用父类具体方法
" 实现逻辑
ENDMETHOD.
ENDCLASS.
三、适用场景深度对比
3.1 接口适用场景
#mermaid-svg-8clcDRSVYHS0NyPL{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-8clcDRSVYHS0NyPL .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8clcDRSVYHS0NyPL .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8clcDRSVYHS0NyPL .error-icon{fill:#552222;}#mermaid-svg-8clcDRSVYHS0NyPL .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8clcDRSVYHS0NyPL .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8clcDRSVYHS0NyPL .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8clcDRSVYHS0NyPL .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8clcDRSVYHS0NyPL .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8clcDRSVYHS0NyPL .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8clcDRSVYHS0NyPL .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8clcDRSVYHS0NyPL .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8clcDRSVYHS0NyPL .marker.cross{stroke:#333333;}#mermaid-svg-8clcDRSVYHS0NyPL svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8clcDRSVYHS0NyPL p{margin:0;}#mermaid-svg-8clcDRSVYHS0NyPL .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-8clcDRSVYHS0NyPL .cluster-label text{fill:#333;}#mermaid-svg-8clcDRSVYHS0NyPL .cluster-label span{color:#333;}#mermaid-svg-8clcDRSVYHS0NyPL .cluster-label span p{background-color:transparent;}#mermaid-svg-8clcDRSVYHS0NyPL .label text,#mermaid-svg-8clcDRSVYHS0NyPL span{fill:#333;color:#333;}#mermaid-svg-8clcDRSVYHS0NyPL .node rect,#mermaid-svg-8clcDRSVYHS0NyPL .node circle,#mermaid-svg-8clcDRSVYHS0NyPL .node ellipse,#mermaid-svg-8clcDRSVYHS0NyPL .node polygon,#mermaid-svg-8clcDRSVYHS0NyPL .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8clcDRSVYHS0NyPL .rough-node .label text,#mermaid-svg-8clcDRSVYHS0NyPL .node .label text,#mermaid-svg-8clcDRSVYHS0NyPL .image-shape .label,#mermaid-svg-8clcDRSVYHS0NyPL .icon-shape .label{text-anchor:middle;}#mermaid-svg-8clcDRSVYHS0NyPL .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-8clcDRSVYHS0NyPL .rough-node .label,#mermaid-svg-8clcDRSVYHS0NyPL .node .label,#mermaid-svg-8clcDRSVYHS0NyPL .image-shape .label,#mermaid-svg-8clcDRSVYHS0NyPL .icon-shape .label{text-align:center;}#mermaid-svg-8clcDRSVYHS0NyPL .node.clickable{cursor:pointer;}#mermaid-svg-8clcDRSVYHS0NyPL .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-8clcDRSVYHS0NyPL .arrowheadPath{fill:#333333;}#mermaid-svg-8clcDRSVYHS0NyPL .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8clcDRSVYHS0NyPL .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8clcDRSVYHS0NyPL .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8clcDRSVYHS0NyPL .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-8clcDRSVYHS0NyPL .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8clcDRSVYHS0NyPL .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-8clcDRSVYHS0NyPL .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8clcDRSVYHS0NyPL .cluster text{fill:#333;}#mermaid-svg-8clcDRSVYHS0NyPL .cluster span{color:#333;}#mermaid-svg-8clcDRSVYHS0NyPL div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-8clcDRSVYHS0NyPL .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-8clcDRSVYHS0NyPL rect.text{fill:none;stroke-width:0;}#mermaid-svg-8clcDRSVYHS0NyPL .icon-shape,#mermaid-svg-8clcDRSVYHS0NyPL .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8clcDRSVYHS0NyPL .icon-shape p,#mermaid-svg-8clcDRSVYHS0NyPL .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-8clcDRSVYHS0NyPL .icon-shape .label rect,#mermaid-svg-8clcDRSVYHS0NyPL .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8clcDRSVYHS0NyPL .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-8clcDRSVYHS0NyPL .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-8clcDRSVYHS0NyPL :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 接口适用场景
定义行为契约
能力组合
解耦调用方
跨模块交互
| 场景类型 | 说明 | 典型示例 |
|---|---|---|
| 行为契约 | 不同类需有相同的行为 | 结算、审批、导出 |
| 能力组合 | 一个类需具备多种能力 | 日志记录 + 权限校验 + 数据导出 |
| 解耦调用方 | 调用方只依赖接口,不依赖具体实现 | 策略模式、工厂模式 |
| 跨模块交互 | 不同模块间通过接口交互 | 模块间API定义 |
3.2 抽象类适用场景
#mermaid-svg-yZvah9W4Lguz2HEL{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-yZvah9W4Lguz2HEL .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-yZvah9W4Lguz2HEL .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-yZvah9W4Lguz2HEL .error-icon{fill:#552222;}#mermaid-svg-yZvah9W4Lguz2HEL .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-yZvah9W4Lguz2HEL .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-yZvah9W4Lguz2HEL .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-yZvah9W4Lguz2HEL .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-yZvah9W4Lguz2HEL .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-yZvah9W4Lguz2HEL .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-yZvah9W4Lguz2HEL .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-yZvah9W4Lguz2HEL .marker{fill:#333333;stroke:#333333;}#mermaid-svg-yZvah9W4Lguz2HEL .marker.cross{stroke:#333333;}#mermaid-svg-yZvah9W4Lguz2HEL svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-yZvah9W4Lguz2HEL p{margin:0;}#mermaid-svg-yZvah9W4Lguz2HEL .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-yZvah9W4Lguz2HEL .cluster-label text{fill:#333;}#mermaid-svg-yZvah9W4Lguz2HEL .cluster-label span{color:#333;}#mermaid-svg-yZvah9W4Lguz2HEL .cluster-label span p{background-color:transparent;}#mermaid-svg-yZvah9W4Lguz2HEL .label text,#mermaid-svg-yZvah9W4Lguz2HEL span{fill:#333;color:#333;}#mermaid-svg-yZvah9W4Lguz2HEL .node rect,#mermaid-svg-yZvah9W4Lguz2HEL .node circle,#mermaid-svg-yZvah9W4Lguz2HEL .node ellipse,#mermaid-svg-yZvah9W4Lguz2HEL .node polygon,#mermaid-svg-yZvah9W4Lguz2HEL .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-yZvah9W4Lguz2HEL .rough-node .label text,#mermaid-svg-yZvah9W4Lguz2HEL .node .label text,#mermaid-svg-yZvah9W4Lguz2HEL .image-shape .label,#mermaid-svg-yZvah9W4Lguz2HEL .icon-shape .label{text-anchor:middle;}#mermaid-svg-yZvah9W4Lguz2HEL .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-yZvah9W4Lguz2HEL .rough-node .label,#mermaid-svg-yZvah9W4Lguz2HEL .node .label,#mermaid-svg-yZvah9W4Lguz2HEL .image-shape .label,#mermaid-svg-yZvah9W4Lguz2HEL .icon-shape .label{text-align:center;}#mermaid-svg-yZvah9W4Lguz2HEL .node.clickable{cursor:pointer;}#mermaid-svg-yZvah9W4Lguz2HEL .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-yZvah9W4Lguz2HEL .arrowheadPath{fill:#333333;}#mermaid-svg-yZvah9W4Lguz2HEL .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-yZvah9W4Lguz2HEL .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-yZvah9W4Lguz2HEL .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yZvah9W4Lguz2HEL .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-yZvah9W4Lguz2HEL .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yZvah9W4Lguz2HEL .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-yZvah9W4Lguz2HEL .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-yZvah9W4Lguz2HEL .cluster text{fill:#333;}#mermaid-svg-yZvah9W4Lguz2HEL .cluster span{color:#333;}#mermaid-svg-yZvah9W4Lguz2HEL div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-yZvah9W4Lguz2HEL .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-yZvah9W4Lguz2HEL rect.text{fill:none;stroke-width:0;}#mermaid-svg-yZvah9W4Lguz2HEL .icon-shape,#mermaid-svg-yZvah9W4Lguz2HEL .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yZvah9W4Lguz2HEL .icon-shape p,#mermaid-svg-yZvah9W4Lguz2HEL .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-yZvah9W4Lguz2HEL .icon-shape .label rect,#mermaid-svg-yZvah9W4Lguz2HEL .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yZvah9W4Lguz2HEL .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-yZvah9W4Lguz2HEL .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-yZvah9W4Lguz2HEL :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 抽象类适用场景
模板方法
代码复用
层级结构
强制实现
| 场景类型 | 说明 | 典型示例 |
|---|---|---|
| 模板方法 | 固定流程骨架,子类实现具体步骤 | 审批流程、结算流程 |
| 代码复用 | 多个子类共享共同逻辑 | 验证、状态更新 |
| 层级结构 | 表达"is-a"关系 | 采购订单是订单的一种 |
| 强制实现 | 通过抽象方法强制子类实现特定功能 | 确保子类完整性 |
3.3 典型业务场景选型指南
| 业务场景 | 推荐方式 | 选型理由 |
|---|---|---|
| 不同供应商接口对接 | 🔵 接口 | 统一契约,不同实现 |
| 不同类型订单结算 | 🔶 抽象类 | 共同流程 + 不同计算 |
| 日志记录功能 | 🔵 接口 | 能力组合,多个类需要 |
| 审批流程 | 🔶 抽象类 | 固定流程骨架 |
| 数据导出(Excel/PDF/CSV) | 🔵 接口 | 统一接口,多种格式 |
| 权限校验功能 | 🔵 接口 | 能力组合 |
| 报表生成 | 🔶 抽象类 | 共同流程(查询→计算→展示) |
| 消息通知(邮件/短信/推送) | 🔵 接口 | 统一接口,多种方式 |
四、选型判断标准
4.1 选型决策流程图
#mermaid-svg-CqtforvtrXqEMxZx{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-CqtforvtrXqEMxZx .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-CqtforvtrXqEMxZx .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-CqtforvtrXqEMxZx .error-icon{fill:#552222;}#mermaid-svg-CqtforvtrXqEMxZx .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-CqtforvtrXqEMxZx .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-CqtforvtrXqEMxZx .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-CqtforvtrXqEMxZx .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-CqtforvtrXqEMxZx .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-CqtforvtrXqEMxZx .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-CqtforvtrXqEMxZx .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-CqtforvtrXqEMxZx .marker{fill:#333333;stroke:#333333;}#mermaid-svg-CqtforvtrXqEMxZx .marker.cross{stroke:#333333;}#mermaid-svg-CqtforvtrXqEMxZx svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-CqtforvtrXqEMxZx p{margin:0;}#mermaid-svg-CqtforvtrXqEMxZx .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-CqtforvtrXqEMxZx .cluster-label text{fill:#333;}#mermaid-svg-CqtforvtrXqEMxZx .cluster-label span{color:#333;}#mermaid-svg-CqtforvtrXqEMxZx .cluster-label span p{background-color:transparent;}#mermaid-svg-CqtforvtrXqEMxZx .label text,#mermaid-svg-CqtforvtrXqEMxZx span{fill:#333;color:#333;}#mermaid-svg-CqtforvtrXqEMxZx .node rect,#mermaid-svg-CqtforvtrXqEMxZx .node circle,#mermaid-svg-CqtforvtrXqEMxZx .node ellipse,#mermaid-svg-CqtforvtrXqEMxZx .node polygon,#mermaid-svg-CqtforvtrXqEMxZx .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-CqtforvtrXqEMxZx .rough-node .label text,#mermaid-svg-CqtforvtrXqEMxZx .node .label text,#mermaid-svg-CqtforvtrXqEMxZx .image-shape .label,#mermaid-svg-CqtforvtrXqEMxZx .icon-shape .label{text-anchor:middle;}#mermaid-svg-CqtforvtrXqEMxZx .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-CqtforvtrXqEMxZx .rough-node .label,#mermaid-svg-CqtforvtrXqEMxZx .node .label,#mermaid-svg-CqtforvtrXqEMxZx .image-shape .label,#mermaid-svg-CqtforvtrXqEMxZx .icon-shape .label{text-align:center;}#mermaid-svg-CqtforvtrXqEMxZx .node.clickable{cursor:pointer;}#mermaid-svg-CqtforvtrXqEMxZx .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-CqtforvtrXqEMxZx .arrowheadPath{fill:#333333;}#mermaid-svg-CqtforvtrXqEMxZx .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-CqtforvtrXqEMxZx .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-CqtforvtrXqEMxZx .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CqtforvtrXqEMxZx .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-CqtforvtrXqEMxZx .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CqtforvtrXqEMxZx .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-CqtforvtrXqEMxZx .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-CqtforvtrXqEMxZx .cluster text{fill:#333;}#mermaid-svg-CqtforvtrXqEMxZx .cluster span{color:#333;}#mermaid-svg-CqtforvtrXqEMxZx div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-CqtforvtrXqEMxZx .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-CqtforvtrXqEMxZx rect.text{fill:none;stroke-width:0;}#mermaid-svg-CqtforvtrXqEMxZx .icon-shape,#mermaid-svg-CqtforvtrXqEMxZx .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CqtforvtrXqEMxZx .icon-shape p,#mermaid-svg-CqtforvtrXqEMxZx .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-CqtforvtrXqEMxZx .icon-shape .label rect,#mermaid-svg-CqtforvtrXqEMxZx .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CqtforvtrXqEMxZx .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-CqtforvtrXqEMxZx .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-CqtforvtrXqEMxZx :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
是
否
是
否
是
否
🎯 需要设计扩展点
需要代码复用?
需要共享属性
或具体方法?
表达 'is-a'
层级关系?
🔶 抽象类
需要多重实现?
🔵 接口
🔶 抽象类 或 🔵 接口
4.2 选型对照速查表
| 判断条件 | ✅ 接口 | ✅ 抽象类 |
|---|---|---|
| 需要代码复用 | ❌ | ✅ |
| 需要共享属性 | ❌ | ✅ |
| 需要多重实现 | ✅ | ❌ |
| 表达"is-a"关系 | ❌ | ✅ |
| 表达"has-a"能力 | ✅ | ❌ |
| 定义行为契约 | ✅ | ✅ |
| 强制子类实现 | ✅ | ✅ |
| 跨模块解耦 | ✅ | ❌ |
4.3 实际项目选型策略
#mermaid-svg-x7WNsggaC6DI7lBA{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-x7WNsggaC6DI7lBA .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-x7WNsggaC6DI7lBA .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-x7WNsggaC6DI7lBA .error-icon{fill:#552222;}#mermaid-svg-x7WNsggaC6DI7lBA .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-x7WNsggaC6DI7lBA .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-x7WNsggaC6DI7lBA .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-x7WNsggaC6DI7lBA .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-x7WNsggaC6DI7lBA .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-x7WNsggaC6DI7lBA .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-x7WNsggaC6DI7lBA .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-x7WNsggaC6DI7lBA .marker{fill:#333333;stroke:#333333;}#mermaid-svg-x7WNsggaC6DI7lBA .marker.cross{stroke:#333333;}#mermaid-svg-x7WNsggaC6DI7lBA svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-x7WNsggaC6DI7lBA p{margin:0;}#mermaid-svg-x7WNsggaC6DI7lBA .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-x7WNsggaC6DI7lBA .cluster-label text{fill:#333;}#mermaid-svg-x7WNsggaC6DI7lBA .cluster-label span{color:#333;}#mermaid-svg-x7WNsggaC6DI7lBA .cluster-label span p{background-color:transparent;}#mermaid-svg-x7WNsggaC6DI7lBA .label text,#mermaid-svg-x7WNsggaC6DI7lBA span{fill:#333;color:#333;}#mermaid-svg-x7WNsggaC6DI7lBA .node rect,#mermaid-svg-x7WNsggaC6DI7lBA .node circle,#mermaid-svg-x7WNsggaC6DI7lBA .node ellipse,#mermaid-svg-x7WNsggaC6DI7lBA .node polygon,#mermaid-svg-x7WNsggaC6DI7lBA .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-x7WNsggaC6DI7lBA .rough-node .label text,#mermaid-svg-x7WNsggaC6DI7lBA .node .label text,#mermaid-svg-x7WNsggaC6DI7lBA .image-shape .label,#mermaid-svg-x7WNsggaC6DI7lBA .icon-shape .label{text-anchor:middle;}#mermaid-svg-x7WNsggaC6DI7lBA .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-x7WNsggaC6DI7lBA .rough-node .label,#mermaid-svg-x7WNsggaC6DI7lBA .node .label,#mermaid-svg-x7WNsggaC6DI7lBA .image-shape .label,#mermaid-svg-x7WNsggaC6DI7lBA .icon-shape .label{text-align:center;}#mermaid-svg-x7WNsggaC6DI7lBA .node.clickable{cursor:pointer;}#mermaid-svg-x7WNsggaC6DI7lBA .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-x7WNsggaC6DI7lBA .arrowheadPath{fill:#333333;}#mermaid-svg-x7WNsggaC6DI7lBA .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-x7WNsggaC6DI7lBA .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-x7WNsggaC6DI7lBA .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-x7WNsggaC6DI7lBA .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-x7WNsggaC6DI7lBA .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-x7WNsggaC6DI7lBA .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-x7WNsggaC6DI7lBA .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-x7WNsggaC6DI7lBA .cluster text{fill:#333;}#mermaid-svg-x7WNsggaC6DI7lBA .cluster span{color:#333;}#mermaid-svg-x7WNsggaC6DI7lBA div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-x7WNsggaC6DI7lBA .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-x7WNsggaC6DI7lBA rect.text{fill:none;stroke-width:0;}#mermaid-svg-x7WNsggaC6DI7lBA .icon-shape,#mermaid-svg-x7WNsggaC6DI7lBA .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-x7WNsggaC6DI7lBA .icon-shape p,#mermaid-svg-x7WNsggaC6DI7lBA .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-x7WNsggaC6DI7lBA .icon-shape .label rect,#mermaid-svg-x7WNsggaC6DI7lBA .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-x7WNsggaC6DI7lBA .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-x7WNsggaC6DI7lBA .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-x7WNsggaC6DI7lBA :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 选型策略
策略一:接口优先
策略二:抽象类做模板
策略三:组合使用
不确定时优先用接口
更灵活,易于扩展
有明确流程模板时
定义骨架,子类实现步骤
接口定义契约
抽象类提供默认实现
子类按需扩展
五、接口 + 抽象类组合模式(最佳实践)
5.1 组合模式结构
#mermaid-svg-aIMLfLJo7JsKo7vk{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-aIMLfLJo7JsKo7vk .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-aIMLfLJo7JsKo7vk .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-aIMLfLJo7JsKo7vk .error-icon{fill:#552222;}#mermaid-svg-aIMLfLJo7JsKo7vk .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-aIMLfLJo7JsKo7vk .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-aIMLfLJo7JsKo7vk .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-aIMLfLJo7JsKo7vk .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-aIMLfLJo7JsKo7vk .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-aIMLfLJo7JsKo7vk .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-aIMLfLJo7JsKo7vk .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-aIMLfLJo7JsKo7vk .marker{fill:#333333;stroke:#333333;}#mermaid-svg-aIMLfLJo7JsKo7vk .marker.cross{stroke:#333333;}#mermaid-svg-aIMLfLJo7JsKo7vk svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-aIMLfLJo7JsKo7vk p{margin:0;}#mermaid-svg-aIMLfLJo7JsKo7vk .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-aIMLfLJo7JsKo7vk .cluster-label text{fill:#333;}#mermaid-svg-aIMLfLJo7JsKo7vk .cluster-label span{color:#333;}#mermaid-svg-aIMLfLJo7JsKo7vk .cluster-label span p{background-color:transparent;}#mermaid-svg-aIMLfLJo7JsKo7vk .label text,#mermaid-svg-aIMLfLJo7JsKo7vk span{fill:#333;color:#333;}#mermaid-svg-aIMLfLJo7JsKo7vk .node rect,#mermaid-svg-aIMLfLJo7JsKo7vk .node circle,#mermaid-svg-aIMLfLJo7JsKo7vk .node ellipse,#mermaid-svg-aIMLfLJo7JsKo7vk .node polygon,#mermaid-svg-aIMLfLJo7JsKo7vk .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-aIMLfLJo7JsKo7vk .rough-node .label text,#mermaid-svg-aIMLfLJo7JsKo7vk .node .label text,#mermaid-svg-aIMLfLJo7JsKo7vk .image-shape .label,#mermaid-svg-aIMLfLJo7JsKo7vk .icon-shape .label{text-anchor:middle;}#mermaid-svg-aIMLfLJo7JsKo7vk .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-aIMLfLJo7JsKo7vk .rough-node .label,#mermaid-svg-aIMLfLJo7JsKo7vk .node .label,#mermaid-svg-aIMLfLJo7JsKo7vk .image-shape .label,#mermaid-svg-aIMLfLJo7JsKo7vk .icon-shape .label{text-align:center;}#mermaid-svg-aIMLfLJo7JsKo7vk .node.clickable{cursor:pointer;}#mermaid-svg-aIMLfLJo7JsKo7vk .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-aIMLfLJo7JsKo7vk .arrowheadPath{fill:#333333;}#mermaid-svg-aIMLfLJo7JsKo7vk .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-aIMLfLJo7JsKo7vk .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-aIMLfLJo7JsKo7vk .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-aIMLfLJo7JsKo7vk .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-aIMLfLJo7JsKo7vk .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-aIMLfLJo7JsKo7vk .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-aIMLfLJo7JsKo7vk .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-aIMLfLJo7JsKo7vk .cluster text{fill:#333;}#mermaid-svg-aIMLfLJo7JsKo7vk .cluster span{color:#333;}#mermaid-svg-aIMLfLJo7JsKo7vk div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-aIMLfLJo7JsKo7vk .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-aIMLfLJo7JsKo7vk rect.text{fill:none;stroke-width:0;}#mermaid-svg-aIMLfLJo7JsKo7vk .icon-shape,#mermaid-svg-aIMLfLJo7JsKo7vk .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-aIMLfLJo7JsKo7vk .icon-shape p,#mermaid-svg-aIMLfLJo7JsKo7vk .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-aIMLfLJo7JsKo7vk .icon-shape .label rect,#mermaid-svg-aIMLfLJo7JsKo7vk .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-aIMLfLJo7JsKo7vk .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-aIMLfLJo7JsKo7vk .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-aIMLfLJo7JsKo7vk :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 📱 调用层
🟢 实现层
🔶 抽象层
🔵 接口层
继承
继承
继承
zif_settlement
定义行为契约
zcl_settlement_base
实现接口 + 提供默认实现
zcl_standard_settlement
标准订单
zcl_urgent_settlement
紧急订单
zcl_framework_settlement
框架订单
调用方(依赖接口类型)
5.2 完整代码实现
abap
" ================================================================
" 🔵 第一步:接口定义契约
" ================================================================
INTERFACE zif_settlement
PUBLIC.
TYPES: BEGIN OF ty_order,
order_id TYPE ebeln,
amount TYPE netwr,
vendor TYPE lifnr,
END OF ty_order.
METHODS: settle
IMPORTING
is_order TYPE ty_order
RETURNING
VALUE(rv_success) TYPE abap_bool.
METHODS: validate
IMPORTING
is_order TYPE ty_order
RETURNING
VALUE(rv_valid) TYPE abap_bool.
ENDINTERFACE.
" ================================================================
" 🔶 第二步:抽象类提供默认实现
" ================================================================
CLASS zcl_settlement_base DEFINITION ABSTRACT.
PUBLIC SECTION.
INTERFACES: zif_settlement.
PROTECTED SECTION.
DATA: order_data TYPE zif_settlement=>ty_order.
METHODS: validate_order
RETURNING
VALUE(rv_valid) TYPE abap_bool.
METHODS: update_status.
METHODS: calculate_amount ABSTRACT. " 子类实现
ENDCLASS.
CLASS zcl_settlement_base IMPLEMENTATION.
METHOD zif_settlement~settle.
rv_success = abap_false.
order_data = is_order.
IF validate_order( ) = abap_false.
RETURN.
ENDIF.
calculate_amount( ). " 子类特有逻辑
update_status( ). " 共同逻辑
rv_success = abap_true.
ENDMETHOD.
METHOD zif_settlement~validate.
rv_valid = abap_true.
IF order_data-order_id IS INITIAL OR
order_data-amount <= 0 OR
order_data-vendor IS INITIAL.
rv_valid = abap_false.
ENDIF.
ENDMETHOD.
METHOD update_status.
WRITE: / '✅ 更新订单状态为已结算'.
ENDMETHOD.
ENDCLASS.
" ================================================================
" 🟢 第三步:子类实现抽象方法
" ================================================================
CLASS zcl_standard_settlement DEFINITION
INHERITING FROM zcl_settlement_base.
PROTECTED SECTION.
METHODS: calculate_amount.
ENDCLASS.
CLASS zcl_standard_settlement IMPLEMENTATION.
METHOD calculate_amount.
WRITE: / '📋 标准订单结算金额:', order_data-amount.
ENDMETHOD.
ENDCLASS.
CLASS zcl_urgent_settlement DEFINITION
INHERITING FROM zcl_settlement_base.
PROTECTED SECTION.
METHODS: calculate_amount.
ENDCLASS.
CLASS zcl_urgent_settlement IMPLEMENTATION.
METHOD calculate_amount.
WRITE: / '📋 紧急订单结算金额:', order_data-amount * 1.02.
ENDMETHOD.
ENDCLASS.
" ================================================================
" 📱 第四步:调用方依赖接口
" ================================================================
DATA(lo_settlement) TYPE REF TO zif_settlement.
lo_settlement = NEW zcl_standard_settlement( ).
lo_settlement->settle( is_order = ls_order ).
lo_settlement = NEW zcl_urgent_settlement( ).
lo_settlement->settle( is_order = ls_order ).
六、常见设计失误与优化方案
6.1 失误一:用抽象类实现能力组合 ❌
#mermaid-svg-9hfBpb5SULVtnSG4{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-9hfBpb5SULVtnSG4 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-9hfBpb5SULVtnSG4 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-9hfBpb5SULVtnSG4 .error-icon{fill:#552222;}#mermaid-svg-9hfBpb5SULVtnSG4 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-9hfBpb5SULVtnSG4 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-9hfBpb5SULVtnSG4 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-9hfBpb5SULVtnSG4 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-9hfBpb5SULVtnSG4 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-9hfBpb5SULVtnSG4 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-9hfBpb5SULVtnSG4 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-9hfBpb5SULVtnSG4 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-9hfBpb5SULVtnSG4 .marker.cross{stroke:#333333;}#mermaid-svg-9hfBpb5SULVtnSG4 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-9hfBpb5SULVtnSG4 p{margin:0;}#mermaid-svg-9hfBpb5SULVtnSG4 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-9hfBpb5SULVtnSG4 .cluster-label text{fill:#333;}#mermaid-svg-9hfBpb5SULVtnSG4 .cluster-label span{color:#333;}#mermaid-svg-9hfBpb5SULVtnSG4 .cluster-label span p{background-color:transparent;}#mermaid-svg-9hfBpb5SULVtnSG4 .label text,#mermaid-svg-9hfBpb5SULVtnSG4 span{fill:#333;color:#333;}#mermaid-svg-9hfBpb5SULVtnSG4 .node rect,#mermaid-svg-9hfBpb5SULVtnSG4 .node circle,#mermaid-svg-9hfBpb5SULVtnSG4 .node ellipse,#mermaid-svg-9hfBpb5SULVtnSG4 .node polygon,#mermaid-svg-9hfBpb5SULVtnSG4 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-9hfBpb5SULVtnSG4 .rough-node .label text,#mermaid-svg-9hfBpb5SULVtnSG4 .node .label text,#mermaid-svg-9hfBpb5SULVtnSG4 .image-shape .label,#mermaid-svg-9hfBpb5SULVtnSG4 .icon-shape .label{text-anchor:middle;}#mermaid-svg-9hfBpb5SULVtnSG4 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-9hfBpb5SULVtnSG4 .rough-node .label,#mermaid-svg-9hfBpb5SULVtnSG4 .node .label,#mermaid-svg-9hfBpb5SULVtnSG4 .image-shape .label,#mermaid-svg-9hfBpb5SULVtnSG4 .icon-shape .label{text-align:center;}#mermaid-svg-9hfBpb5SULVtnSG4 .node.clickable{cursor:pointer;}#mermaid-svg-9hfBpb5SULVtnSG4 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-9hfBpb5SULVtnSG4 .arrowheadPath{fill:#333333;}#mermaid-svg-9hfBpb5SULVtnSG4 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-9hfBpb5SULVtnSG4 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-9hfBpb5SULVtnSG4 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-9hfBpb5SULVtnSG4 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-9hfBpb5SULVtnSG4 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-9hfBpb5SULVtnSG4 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-9hfBpb5SULVtnSG4 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-9hfBpb5SULVtnSG4 .cluster text{fill:#333;}#mermaid-svg-9hfBpb5SULVtnSG4 .cluster span{color:#333;}#mermaid-svg-9hfBpb5SULVtnSG4 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-9hfBpb5SULVtnSG4 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-9hfBpb5SULVtnSG4 rect.text{fill:none;stroke-width:0;}#mermaid-svg-9hfBpb5SULVtnSG4 .icon-shape,#mermaid-svg-9hfBpb5SULVtnSG4 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-9hfBpb5SULVtnSG4 .icon-shape p,#mermaid-svg-9hfBpb5SULVtnSG4 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-9hfBpb5SULVtnSG4 .icon-shape .label rect,#mermaid-svg-9hfBpb5SULVtnSG4 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-9hfBpb5SULVtnSG4 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-9hfBpb5SULVtnSG4 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-9hfBpb5SULVtnSG4 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ❌ 错误
抽象类 A
抽象类 B
❌ 无法多重继承
abap
" ❌ 错误:ABAP 不支持多重继承
CLASS zcl_logger DEFINITION ABSTRACT.
METHODS: log.
ENDCLASS.
CLASS zcl_authorizer DEFINITION ABSTRACT.
METHODS: authorize.
ENDCLASS.
CLASS zcl_business_service DEFINITION
INHERITING FROM zcl_logger, zcl_authorizer. " ❌ 编译错误
ENDCLASS.
abap
" ✅ 正确:使用接口实现能力组合
INTERFACE zif_logger.
METHODS: log.
ENDINTERFACE.
INTERFACE zif_authorizer.
METHODS: authorize.
ENDINTERFACE.
CLASS zcl_business_service DEFINITION.
PUBLIC SECTION.
INTERFACES: zif_logger, zif_authorizer. " ✅ 可实现多个接口
ENDCLASS.
6.2 失误二:用接口代替抽象类导致代码重复 ❌
#mermaid-svg-8EooveMHKQiBMvrX{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-8EooveMHKQiBMvrX .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8EooveMHKQiBMvrX .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8EooveMHKQiBMvrX .error-icon{fill:#552222;}#mermaid-svg-8EooveMHKQiBMvrX .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8EooveMHKQiBMvrX .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8EooveMHKQiBMvrX .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8EooveMHKQiBMvrX .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8EooveMHKQiBMvrX .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8EooveMHKQiBMvrX .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8EooveMHKQiBMvrX .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8EooveMHKQiBMvrX .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8EooveMHKQiBMvrX .marker.cross{stroke:#333333;}#mermaid-svg-8EooveMHKQiBMvrX svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8EooveMHKQiBMvrX p{margin:0;}#mermaid-svg-8EooveMHKQiBMvrX .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-8EooveMHKQiBMvrX .cluster-label text{fill:#333;}#mermaid-svg-8EooveMHKQiBMvrX .cluster-label span{color:#333;}#mermaid-svg-8EooveMHKQiBMvrX .cluster-label span p{background-color:transparent;}#mermaid-svg-8EooveMHKQiBMvrX .label text,#mermaid-svg-8EooveMHKQiBMvrX span{fill:#333;color:#333;}#mermaid-svg-8EooveMHKQiBMvrX .node rect,#mermaid-svg-8EooveMHKQiBMvrX .node circle,#mermaid-svg-8EooveMHKQiBMvrX .node ellipse,#mermaid-svg-8EooveMHKQiBMvrX .node polygon,#mermaid-svg-8EooveMHKQiBMvrX .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8EooveMHKQiBMvrX .rough-node .label text,#mermaid-svg-8EooveMHKQiBMvrX .node .label text,#mermaid-svg-8EooveMHKQiBMvrX .image-shape .label,#mermaid-svg-8EooveMHKQiBMvrX .icon-shape .label{text-anchor:middle;}#mermaid-svg-8EooveMHKQiBMvrX .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-8EooveMHKQiBMvrX .rough-node .label,#mermaid-svg-8EooveMHKQiBMvrX .node .label,#mermaid-svg-8EooveMHKQiBMvrX .image-shape .label,#mermaid-svg-8EooveMHKQiBMvrX .icon-shape .label{text-align:center;}#mermaid-svg-8EooveMHKQiBMvrX .node.clickable{cursor:pointer;}#mermaid-svg-8EooveMHKQiBMvrX .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-8EooveMHKQiBMvrX .arrowheadPath{fill:#333333;}#mermaid-svg-8EooveMHKQiBMvrX .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8EooveMHKQiBMvrX .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8EooveMHKQiBMvrX .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8EooveMHKQiBMvrX .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-8EooveMHKQiBMvrX .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8EooveMHKQiBMvrX .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-8EooveMHKQiBMvrX .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8EooveMHKQiBMvrX .cluster text{fill:#333;}#mermaid-svg-8EooveMHKQiBMvrX .cluster span{color:#333;}#mermaid-svg-8EooveMHKQiBMvrX div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-8EooveMHKQiBMvrX .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-8EooveMHKQiBMvrX rect.text{fill:none;stroke-width:0;}#mermaid-svg-8EooveMHKQiBMvrX .icon-shape,#mermaid-svg-8EooveMHKQiBMvrX .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8EooveMHKQiBMvrX .icon-shape p,#mermaid-svg-8EooveMHKQiBMvrX .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-8EooveMHKQiBMvrX .icon-shape .label rect,#mermaid-svg-8EooveMHKQiBMvrX .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8EooveMHKQiBMvrX .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-8EooveMHKQiBMvrX .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-8EooveMHKQiBMvrX :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 接口
实现类A
实现类B
实现类C
重复代码1
重复代码1
重复代码1
abap
" ✅ 正确:抽象类提供默认实现
CLASS zcl_settlement_base DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS: settle ABSTRACT.
METHODS: validate. " ✅ 默认实现(只写一次)
METHODS: update_status. " ✅ 默认实现(只写一次)
ENDCLASS.
" 子类只需实现差异部分
CLASS zcl_standard_settlement DEFINITION
INHERITING FROM zcl_settlement_base.
PUBLIC SECTION.
METHODS: settle REDEFINITION.
ENDCLASS.
6.3 失误三:接口定义过于宽泛 ❌
abap
" ❌ 错误:接口职责过多
INTERFACE zif_business_object.
METHODS: create, update, delete. " CRUD
METHODS: approve. " 审批(非必需)
METHODS: settle. " 结算(非必需)
METHODS: export. " 导出(非必需)
ENDINTERFACE.
abap
" ✅ 正确:接口职责单一
INTERFACE zif_crud. " 基础 CRUD
METHODS: create, update, delete.
ENDINTERFACE.
INTERFACE zif_approveable. " 可审批
METHODS: approve.
ENDINTERFACE.
INTERFACE zif_settlement. " 可结算
METHODS: settle.
ENDINTERFACE.
" 采购订单 → 需要 CRUD + 审批 + 结算
CLASS zcl_purchase_order DEFINITION.
PUBLIC SECTION.
INTERFACES: zif_crud, zif_approveable, zif_settlement.
ENDCLASS.
" 物料主数据 → 只需要 CRUD
CLASS zcl_material DEFINITION.
PUBLIC SECTION.
INTERFACES: zif_crud.
ENDCLASS.
6.4 失误四:抽象类过度设计 ❌
abap
" ❌ 错误:具体方法过多,子类难以扩展
CLASS zcl_report_generator DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS: generate_report.
PROTECTED SECTION.
METHODS: query_data. " 具体实现
METHODS: calculate. " 具体实现
METHODS: format_output. " 具体实现
METHODS: send_email. " 具体实现
ENDCLASS.
abap
" ✅ 正确:合理搭配抽象与具体方法
CLASS zcl_report_generator DEFINITION ABSTRACT.
PUBLIC SECTION.
METHODS: generate_report. " 模板方法
PROTECTED SECTION.
METHODS: query_data ABSTRACT. " 必须实现
METHODS: calculate. " 默认实现,可重写
METHODS: format_output ABSTRACT. " 必须实现
METHODS: send_email. " 默认实现
ENDCLASS.
七、快速参考卡片
接口 vs 抽象类速查表
| 维度 | 接口(Interface) | 抽象类(Abstract Class) |
|---|---|---|
| 定义关键字 | INTERFACE |
CLASS ... ABSTRACT |
| 方法实现 | ❌ 只声明 | ✅ 可含具体方法 |
| 属性支持 | ❌ 仅常量 | ✅ 完整属性 |
| 多重实现 | ✅ | ❌ |
| 适用场景 | 能力组合、解耦 | 代码复用、模板 |
| 选型口诀 | 定义"做什么" | 定义"怎么做" |
选型决策口诀
🤔 不确定用哪个?记住三问:
1. 需要代码复用吗? → 需要 → 考虑抽象类
2. 需要多重能力吗? → 需要 → 使用接口
3. 既是又是怎么办? → 接口 + 抽象类 组合使用
八、总结
#mermaid-svg-R2uMwEbQYwEKetV5{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-R2uMwEbQYwEKetV5 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-R2uMwEbQYwEKetV5 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-R2uMwEbQYwEKetV5 .error-icon{fill:#552222;}#mermaid-svg-R2uMwEbQYwEKetV5 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-R2uMwEbQYwEKetV5 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-R2uMwEbQYwEKetV5 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-R2uMwEbQYwEKetV5 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-R2uMwEbQYwEKetV5 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-R2uMwEbQYwEKetV5 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-R2uMwEbQYwEKetV5 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-R2uMwEbQYwEKetV5 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-R2uMwEbQYwEKetV5 .marker.cross{stroke:#333333;}#mermaid-svg-R2uMwEbQYwEKetV5 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-R2uMwEbQYwEKetV5 p{margin:0;}#mermaid-svg-R2uMwEbQYwEKetV5 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-R2uMwEbQYwEKetV5 .cluster-label text{fill:#333;}#mermaid-svg-R2uMwEbQYwEKetV5 .cluster-label span{color:#333;}#mermaid-svg-R2uMwEbQYwEKetV5 .cluster-label span p{background-color:transparent;}#mermaid-svg-R2uMwEbQYwEKetV5 .label text,#mermaid-svg-R2uMwEbQYwEKetV5 span{fill:#333;color:#333;}#mermaid-svg-R2uMwEbQYwEKetV5 .node rect,#mermaid-svg-R2uMwEbQYwEKetV5 .node circle,#mermaid-svg-R2uMwEbQYwEKetV5 .node ellipse,#mermaid-svg-R2uMwEbQYwEKetV5 .node polygon,#mermaid-svg-R2uMwEbQYwEKetV5 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-R2uMwEbQYwEKetV5 .rough-node .label text,#mermaid-svg-R2uMwEbQYwEKetV5 .node .label text,#mermaid-svg-R2uMwEbQYwEKetV5 .image-shape .label,#mermaid-svg-R2uMwEbQYwEKetV5 .icon-shape .label{text-anchor:middle;}#mermaid-svg-R2uMwEbQYwEKetV5 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-R2uMwEbQYwEKetV5 .rough-node .label,#mermaid-svg-R2uMwEbQYwEKetV5 .node .label,#mermaid-svg-R2uMwEbQYwEKetV5 .image-shape .label,#mermaid-svg-R2uMwEbQYwEKetV5 .icon-shape .label{text-align:center;}#mermaid-svg-R2uMwEbQYwEKetV5 .node.clickable{cursor:pointer;}#mermaid-svg-R2uMwEbQYwEKetV5 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-R2uMwEbQYwEKetV5 .arrowheadPath{fill:#333333;}#mermaid-svg-R2uMwEbQYwEKetV5 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-R2uMwEbQYwEKetV5 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-R2uMwEbQYwEKetV5 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-R2uMwEbQYwEKetV5 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-R2uMwEbQYwEKetV5 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-R2uMwEbQYwEKetV5 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-R2uMwEbQYwEKetV5 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-R2uMwEbQYwEKetV5 .cluster text{fill:#333;}#mermaid-svg-R2uMwEbQYwEKetV5 .cluster span{color:#333;}#mermaid-svg-R2uMwEbQYwEKetV5 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-R2uMwEbQYwEKetV5 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-R2uMwEbQYwEKetV5 rect.text{fill:none;stroke-width:0;}#mermaid-svg-R2uMwEbQYwEKetV5 .icon-shape,#mermaid-svg-R2uMwEbQYwEKetV5 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-R2uMwEbQYwEKetV5 .icon-shape p,#mermaid-svg-R2uMwEbQYwEKetV5 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-R2uMwEbQYwEKetV5 .icon-shape .label rect,#mermaid-svg-R2uMwEbQYwEKetV5 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-R2uMwEbQYwEKetV5 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-R2uMwEbQYwEKetV5 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-R2uMwEbQYwEKetV5 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 扩展方式
🔵 接口
🔶 抽象类
✅ 多重实现
✅ 能力组合
✅ 解耦
✅ 代码复用
✅ 模板方法
✅ 共享属性
💡 最佳实践
接口定义契约
抽象类提供默认实现
子类按需扩展
| 维度 | 接口 | 抽象类 |
|---|---|---|
| 核心价值 | 定义行为契约、能力组合 | 代码复用、模板方法 |
| 继承方式 | 多重实现(INTERFACES) |
单继承(INHERITING FROM) |
| 属性支持 | ❌ 仅常量和类型 | ✅ 完整属性支持 |
| 方法实现 | 只声明 | 可含具体方法 |
| 适用场景 | 行为规范、能力组合、解耦 | 代码复用、模板方法、层级结构 |
| 灵活性 | 高 | 中等 |
| 选型口诀 | 定义"做什么" | 定义"怎么做" |
核心要点
- 接口 :定义"做什么"(What),支持多重实现,适合能力组合 和解耦
- 抽象类 :定义"怎么做"(How),提供默认实现,适合代码复用 和模板方法
- 组合使用:接口定义契约,抽象类提供默认实现,子类按需扩展
- 选型原则:需要代码复用/共享属性 → 抽象类;需要多重实现/解耦 → 接口
下一篇预告:《多态落地实战:基于接口的动态方法调用与业务逻辑解耦实现》
作者 :爱喝水的鱼丶
版本记录 :2026年7月
验证基准:SAP NetWeaver 7.51
💬 你在实际项目中遇到过接口和抽象类选型困难的场景吗?欢迎在评论区分享你的经验!