类型转换与多态

类型转换与多态 (★★★)

#abap-objects #inheritance #casting #polymorphism

概览表

项目 关键点
Up-cast 子类→父类引用,隐式安全
Down-cast 父类→子类引用,显式 ?=,可能运行时错误
多态 同一接口不同实现,通过动态绑定实现
泛型调用 使用父类/接口引用统一调用

Up-cast (向上转型 / Widening Cast)

1
2
3
4
5
DATA: lo_vehicle TYPE REF TO lcl_vehicle,
lo_car TYPE REF TO lcl_car.

CREATE OBJECT lo_car.
lo_vehicle = lo_car. " Up-cast: 隐式,总是安全

特性

  • 使用 = 赋值
  • 隐式,编译器允许
  • 总是安全 — 子类一定是父类
  • 可见的组件减少(只能访问父类定义的组件)
  • 类型兼容性增加(可以接受更多动态类型)
1
2
3
转换前: lo_car     → 可访问 [Vehicle + Car 组件]
转换后: lo_vehicle → 只能访问 [Vehicle 组件]
视角变窄,但兼容性变宽
💡Up-cast 的典型用途
将不同子类的对象收集到一个统一类型的内表中:
1
2
3
4
5
6
DATA: lt_vehicles TYPE TABLE OF REF TO lcl_vehicle.
lt_vehicles = VALUE #(
( NEW lcl_car( ) ) " 自动 up-cast
( NEW lcl_truck( ) ) " 自动 up-cast
( NEW lcl_bus( ) ) " 自动 up-cast
).

Down-cast (向下转型 / Narrowing Cast)

1
2
3
4
5
6
DATA: lo_vehicle TYPE REF TO lcl_vehicle,
lo_car TYPE REF TO lcl_car.

CREATE OBJECT lo_car.
lo_vehicle = lo_car. " Up-cast
lo_car ?= lo_vehicle. " Down-cast: 需要显式 ?=

特性

  • 使用 ?= 赋值
  • 显式,开发者自己负责
  • 可能失败 — 如果实际对象不是目标类型
  • 失败时触发 CX_SY_MOVE_CAST_ERROR 异常
1
2
安全:  lo_vehicle 实际指向 lcl_car → ?= 成功
危险: lo_vehicle 实际指向 lcl_truck → ?= lcl_car → 运行时错误!

安全的 Down-cast

1
2
3
4
5
6
7
8
9
10
11
" 方法1: TRY-CATCH
TRY.
lo_car ?= lo_vehicle.
CATCH cx_sy_move_cast_error.
" 处理类型不匹配
ENDTRY.

" 方法2: RTTI 类型检查
IF cl_abap_classdescr=>get_relative_name( lo_vehicle ) = 'LCL_CAR'.
lo_car ?= lo_vehicle.
ENDIF.

多态 (Polymorphism)

多态是继承最重要的应用:

  • 通过父类引用调用方法
  • 实际执行的是子类的重定义实现
  • 运行时动态绑定
1
2
3
4
5
6
7
8
9
10
" 创建不同子类对象
DATA: lt_vehicles TYPE TABLE OF REF TO lcl_vehicle.
APPEND NEW lcl_car( ) TO lt_vehicles.
APPEND NEW lcl_truck( ) TO lt_vehicles.
APPEND NEW lcl_bus( ) TO lt_vehicles.

" 统一调用 — 多态!
LOOP AT lt_vehicles INTO DATA(lo_v).
lo_v->display( ). " 每个对象执行自己的 display 实现
ENDLOOP.

多态的工作原理

1
2
3
4
5
6
7
静态类型: lcl_vehicle          → 编译时检查 vehicle 组件
动态类型: 实际的 car/truck/bus → 运行时调用实际实现

lo_v->display( )
→ lo_v 指向 car? → 执行 lcl_car=>display( )
→ lo_v 指向 truck? → 执行 lcl_truck=>display( )
→ lo_v 指向 bus? → 执行 lcl_bus=>display( )

泛型调用 (Generic Calls)

将 up-cast 和多态结合,实现统一的处理逻辑

1
2
3
4
5
6
7
8
" 方法参数使用父类类型
METHODS: process_vehicle
IMPORTING io_vehicle TYPE REF TO lcl_vehicle.

" 可以传入任何子类
process_vehicle( lo_car ).
process_vehicle( lo_truck ).
process_vehicle( lo_bus ).

Up-cast vs Down-cast 对比

特性 Up-cast Down-cast
方向 子→父 父→子
赋值符 = ?=
安全性 总是安全 可能失败
视角 变窄 变宽
兼容性 变宽 变窄
何时使用 收集不同子类 恢复具体类型

考试/测试模式

场景/关键词 答案
“up-cast赋值符” =,隐式安全
“down-cast赋值符” ?=,显式,可能失败
“多态的核心” 父类引用调用方法,运行时动态绑定到子类实现
“何时需要down-cast” 需要访问子类特有组件时
“down-cast失败” 触发 CX_SY_MOVE_CAST_ERROR
“泛型调用的实现” 方法参数使用父类/接口类型