ABAP 面向对象

ABAP 面向对象

🎯 面向对象编程概述

定义

对象导向简化了软件设计,使其更易于理解、维护和重用。面向对象编程(OOP)表示在编写软件时的不同思维方式。

OOP的优势



graph TD
    A[面向对象编程] --> B[简化设计]
    A --> C[易于维护]
    A --> D[代码重用]
    A --> E[易于沟通]
    A --> F[高质量软件]

OOP的美丽

  • 简单性:OOP的表达能力使得更容易按时交付高质量的软件组件
  • 通用语言:解决方案根据现实世界的对象设计,程序员和业务分析师使用通用域语言交换想法
  • 需求发现:沟通的改进有助于揭示隐藏的要求,识别风险
  • 质量提升:提高正在开发的软件的质量

🔍 过程编程 vs 面向对象编程

对比分析

特征 程序导向法 面向对象方法
重点 重点是任务 重点是做那些任务的事情
模块化 程序分为称为函数的小程序 程序组织成类和对象,功能嵌入到类的方法中
数据安全 大多数函数共享全局数据 数据可以被隐藏,不能被外部源访问
可扩展性 修改和扩展现有功能更耗时 新的数据和功能可以轻松添加

📋 ABAP中的面向对象

ABAP的发展历程

  • 最初:ABAP被开发为过程语言(类似于COBOL)
  • 现在:ABAP已适应面向对象范式的原理,引入了ABAP对象
  • 兼容性:ABAP中面向对象的概念与其他现代面向对象语言(如Java或C++)基本相同

ABAP面向对象的核心概念

  1. 类(Class)
  2. 对象(Object)
  3. 继承(Inheritance)
  4. 多态(Polymorphism)

🏗️ 面向对象的主要特点

1. 有效的编程结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
" 良好的类设计示例
CLASS zcl_example DEFINITION.
PUBLIC SECTION.
METHODS:
" 公共方法
calculate_discount
IMPORTING iv_amount TYPE p
EXPORTING ev_discount TYPE p,
get_total
IMPORTING iv_items TYPE i
RETURNING(rv_total) TYPE p.
PRIVATE SECTION.
" 私有数据和方法
DATA: mv_discount_rate TYPE p VALUE 0.10.
METHODS: validate_amount
IMPORTING iv_amount TYPE p.
ENDCLASS.

2. 现实世界的实体建模



classDiagram
    class Customer {
        +String name
        +String id
        +Date registrationDate
        +registerOrder()
        +getDiscount()
    }
    
    class Order {
        +String orderId
        +Date orderDate
        +Double totalAmount
        +addItem()
        +calculateTotal()
    }
    
    class OrderItem {
        +String productId
        +Integer quantity
        +Double price
        +getSubtotal()
    }
    
    Customer "1" -- "0..*" Order : places
    Order "1" -- "1..*" OrderItem : contains

3. 数据安全和访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
CLASS zcl_secure_data DEFINITION.
PUBLIC SECTION.
METHODS:
get_data
RETURNING(value(rv_data)) TYPE string,
set_data
IMPORTING iv_data TYPE string.
PRIVATE SECTION.
DATA: mv_secure_data TYPE string.
ENDCLASS.

" 外部代码只能通过公共方法访问数据
DATA(lo_secure) = NEW zcl_secure_data( ).
lo_secure->set_data( ' confidential information ' ).
" 直接访问 mv_secure_data 会导致编译错误

4. 最小化代码冗余

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
" 使用继承减少重复代码
CLASS zcl_base_vehicle DEFINITION.
PUBLIC SECTION.
METHODS:
start_engine
ABSTRACT, " 抽象方法
get_speed
RETURNING(value(rv_speed)) TYPE i.
ENDCLASS.

" 子类继承并实现
CLASS zcl_car DEFINITION INHERITING FROM zcl_base_vehicle.
PUBLIC SECTION.
METHODS:
start_engine REDEFINITION,
get_speed REDEFINITION.
ENDCLASS.

CLASS zcl_car IMPLEMENTATION.
METHOD start_engine.
WRITE: / 'Car engine started'.
ENDMETHOD.

METHOD get_speed.
rv_speed = 120. " 汽车速度
ENDMETHOD.
ENDCLASS.

5. 数据抽象和封装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
" 封装:隐藏实现细节,只暴露接口
CLASS zcl_bank_account DEFINITION.
PUBLIC SECTION.
METHODS:
deposit
IMPORTING iv_amount TYPE p,
withdraw
IMPORTING iv_amount TYPE p,
get_balance
RETURNING(value(rv_balance)) TYPE p.
PRIVATE SECTION.
DATA: mv_balance TYPE p VALUE 0.
METHODS: validate_amount
IMPORTING iv_amount TYPE p.
ENDCLASS.

" 使用者不需要知道余额如何存储
DATA(lo_account) = NEW zcl_bank_account( ).
lo_account->deposit( 1000 ).
lo_account->withdraw( 200 ).
WRITE: / 'Balance:', lo_account->get_balance( ).

💡 面向对象设计原则

1. 单一职责原则(SRP)

1
2
3
4
5
6
7
8
9
" 每个类只负责一个职责
CLASS zcl_order_service DEFINITION.
PUBLIC SECTION.
METHODS:
save_order
IMPORTING iv_order TYPE zcl_order=>ty_order,
send_confirmation
IMPORTING iv_order_id TYPE vbeln.
ENDCLASS.

2. 开放封闭原则(OCP)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
" 对扩展开放,对修改封闭
CLASS zcl_discount_calculator DEFINITION.
PUBLIC SECTION.
METHODS:
calculate_discount
IMPORTING iv_amount TYPE p
RETURNING(value(rv_discount)) TYPE p.
ENDCLASS.

" 新的折扣类型通过扩展而不是修改来添加
CLASS zcl_vip_discount_calculator DEFINITION
INHERITING FROM zcl_discount_calculator.
PUBLIC SECTION.
METHODS: calculate_discount REDEFINITION.
ENDCLASS.

3. 里氏替换原则(LSP)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
" 子类可以替换父类
CLASS zcl_payment_processor DEFINITION.
PUBLIC SECTION.
METHODS:
process_payment
IMPORTING iv_amount TYPE p
RAISING cx_payment_error.
ENDCLASS.

CLASS zcl_credit_card_processor DEFINITION
INHERITING FROM zcl_payment_processor.
PUBLIC SECTION.
METHODS: process_payment REDEFINITION.
ENDCLASS.

" 可以安全地使用任意处理器
DATA(lo_processor) = NEW zcl_payment_processor( ).
" 或者
DATA(lo_processor2) = NEW zcl_credit_card_processor( ).

4. 接口隔离原则(ISP)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
" 定义专门的接口
INTERFACE zcl_discountable.
METHODS: get_discount_percentage
RETURNING(value(rv_percentage)) TYPE p.
ENDINTERFACE.

INTERFACE zcl_taxable.
METHODS: calculate_tax
IMPORTING iv_amount TYPE p
RETURNING(value(rv_tax)) TYPE p.
ENDINTERFACE.

" 类实现需要的接口
CLASS zcl_product DEFINITION.
PUBLIC SECTION.
INTERFACES: zcl_discountable, zcl_taxable.
ENDCLASS.

🎯 面向对象的实际应用

1. 业务对象建模

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
" 客户类示例
CLASS zcl_customer DEFINITION.
PUBLIC SECTION.
METHODS:
constructor
IMPORTING iv_id TYPE kunnr,
add_order
IMPORTING iv_order TYPE zcl_order=>ty_order,
get_orders
RETURNING(value(rt_orders)) TYPE zcl_order=>tt_orders,
calculate_lifetime_value
RETURNING(value(rv_value)) TYPE p.
PRIVATE SECTION.
DATA: mv_id TYPE kunnr,
mt_orders TYPE zcl_order=>tt_orders.
ENDCLASS.

2. 工厂模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
" 工厂类创建对象
CLASS zcl_factory DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
create_document
IMPORTING iv_type TYPE char1
RETURNING(value(ro_document)) TYPE REF TO zcl_document.
ENDCLASS.

CLASS zcl_factory IMPLEMENTATION.
METHOD create_document.
CASE iv_type.
WHEN 'PDF'.
ro_document = NEW zcl_pdf_document( ).
WHEN 'DOC'.
ro_document = NEW zcl_doc_document( ).
WHEN OTHERS.
RAISE EXCEPTION TYPE cx_document_error.
ENDCASE.
ENDMETHOD.
ENDCLASS.

3. 观察者模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
" 主题接口
INTERFACE zcl_subject.
METHODS:
register_observer
IMPORTING io_observer TYPE REF TO zcl_observer,
notify_observers.
ENDINTERFACE.

" 观察者接口
INTERFACE zcl_observer.
METHODS:
update
IMPORTING iv_message TYPE string.
ENDINTERFACE.

" 具体实现
CLASS zcl_news DEFINITION.
PUBLIC SECTION.
INTERFACES: zcl_subject.
ENDCLASS.

CLASS zcl_email_notifier DEFINITION.
PUBLIC SECTION.
INTERFACES: zcl_observer.
ENDCLASS.

⚠️ 注意事项

1. 避免过度设计

1
2
3
4
5
6
7
8
9
10
11
12
13
" 不必要的复杂化
CLASS zcl_example_too_complex DEFINITION.
" 太多设计模式,简单任务用简单方法
ENDCLASS.

" 更好的方案
CLASS zcl_simple_example DEFINITION.
PUBLIC SECTION.
METHODS:
do_simple_task
IMPORTING iv_input TYPE any
RETURNING(value(rv_result)) TYPE any.
ENDCLASS.

2. 保持类的大小合理

1
2
3
4
5
6
7
8
9
10
" 遵循单一职责原则
CLASS zcl_user_management DEFINITION.
PUBLIC SECTION.
" 用户管理相关方法
METHODS:
create_user,
update_user,
delete_user,
get_user_by_id.
ENDCLASS.

3. 使用合适的访问修饰符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
" 合理使用PUBLIC/PRIVATE/PROTECTED
CLASS zcl_good_design DEFINITION.
PUBLIC SECTION.
" 对外暴露的公共接口
METHODS:
get_public_data
RETURNING(value(rv_data)) TYPE string.
PRIVATE SECTION.
" 内部实现细节
DATA: mv_private_data TYPE string.
METHODS:
calculate_internal_value
RETURNING(value(rv_value)) TYPE i.
ENDCLASS.