类型转换与多态 (★★★) #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 组件] 视角变窄,但兼容性变宽
将不同子类的对象收集到一个统一类型的内表中:
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
“泛型调用的实现”
方法参数使用父类/接口类型