定义接口
学习目标
定义接口。
接口定义
使用接口的原因
使用接口可以定义程序如何处理一个或多个类。在接口中,可以像在类中一样定义方法、属性、类型和常量。这些组件构成了客户端程序如何与相应对象进行交互的描述。但是,接口无法实例化,并且不包含其方法的任何实施。要使概念生效,还需要一个或多个实施接口的类。这意味着它们在其自己的类声明中包括接口,在接口中声明的组件将成为类本身的一部分。如果接口包含方法声明,则实施接口的类还必须提供该方法的实施。

接口有两个重要用途:
为不同的类提供统一的方法:如果您的类与继承无关,但仍应向其用户提供通用服务,则可以在接口中定义通用服务。这可确保每个类都提供具有相同名称和相同签名的方法,以执行特定任务。然后,无论实际寻址哪个类,使用类的程序都可以通过单一方式调用特定功能。
提供复杂类的简化方法:如稍后所述,接口提供对象的受限视图。这使您可以向程序公开一组特定的方法,该程序将根据程序实际需要的功能使用特定类。
观看此示例以了解接口的工作方式。
视频:本节含 SAP 官方视频(视频 ID
1_zaqhaatl),需在 learning.sap.com 在线观看。
接口定义
接口的定义与类的定义部分非常相似。但是,由于接口没有实施,INTERFACE 语句中没有 DEFINITION 附加项。第二个主要区别是接口中没有可见性部分,因为接口的所有组件都是公共的。接口由于其与其他类的交互而有用,因此具有非公共组件没有意义。

在接口定义中,您可以使用类型、属性、常量和方法,并允许实例和静态组件。请记住,接口方法具有定义,但没有实施。这将由实施类提供。
在许多方面,接口类似于抽象超级类。对于需要定义类的通用组件而无需继承的情况(即没有明确的"是"关系),它们提供了一种有用的技术。
实施接口
要在类中实施接口,请使用 INTERFACES 语句。由于接口的所有组件都是公共的,并且您无法更改现有组件的可见性,因此必须在类的公共部分中包含该接口。

一旦您编写了 INTERFACES 语句,程序就会出现语法错误。这是因为接口包含尚未实施的方法。您可以使用快速修复 (Ctrl + 1) 将方法实施添加到类。
在类中声明接口时,必须实现其所有方法。

在类的实现中,必须实施在接口中声明的所有方法。对实施中的方法进行命名时,必须使用完全限定名称,该名称由接口名称和由波浪符连接的方法名称组成。这是因为无法保证方法名称本身是明确的;请记住,组件名称只有在声明它们的类或接口中才能唯一。因此,类可以声明名为 get_partner_attributes 的方法以及接口 lif_partner。
试用:接口定义
创建实施接口 IF_OO_ADT_CLASSRUN 的新类。
切换到 局部类型 标签并将以下代码片段复制到编辑器中:
INTERFACE lif_partner.
METHODS get_partner_attributes.
ENDINTERFACE.
CLASS lcl_travel_Agency DEFINITION.
PUBLIC SECTION.
ENDCLASS.
CLASS lcl_airline DEFINITION.
PUBLIC SECTION.
INTERFACES lif_Partner.
TYPES: BEGIN OF ts_detail,
name TYPE string,
value TYPE string,
END OF ts_detail,
tt_Details TYPE SORTED TABLE OF ts_detail WITH UNIQUE KEY name.
METHODS get_details RETURNING VALUE(rt_details) TYPE tt_details.
ENDCLASS.
CLASS lcl_car_Rental DEFINITION.
PUBLIC SECTION.
interfaces lif_Partner.
TYPES: BEGIN OF ts_info,
name TYPE c LENGTH 20,
value TYPE c LENGTH 20,
END OF ts_info,
tt_Info TYPE SORTED TABLE OF ts_info WITH UNIQUE KEY name.
METHODS get_information RETURNING VALUE(rt_details) TYPE tt_info.
ENDCLASS.
CLASS lcl_airline IMPLEMENTATION.
METHOD get_details.
ENDMETHOD.
METHOD lif_partner~get_partner_attributes.
ENDMETHOD.
ENDCLASS.
CLASS lcl_car_rental IMPLEMENTATION.
METHOD get_information.
ENDMETHOD.
METHOD lif_partner~get_partner_attributes.
ENDMETHOD.
ENDCLASS.
按 Ctrl + F3 激活类。
熟悉代码。
注意
此示例中没有可执行代码。
定义和实施接口
您意识到局部类 LCL_CARRIER 中的方法 GET_OUTPUT 和本地类 LCL_FLIGHT 中的方法 GET_DESCRIPTION 非常相似。为了协调定义,引入接口并在两个类中实施。
模板:
/LRN/CL_S4D401_OOS_INH_USAGE(全局类)
解决方案:
/LRN/CL_S4D401_OOS_INTERFACE(全局类)
任务 1: 复制模板(可选)
复制模板类 /LRN/CL_S4D401_OOS_INH_USAGE。如果已完成上一练习,则可以跳过此任务并继续编辑类 ZCL_##_SOLUTION。
步骤
将类
/LRN/CL_S4D401_OOS_INH_USAGE复制到您自己的包中的类(建议名称:ZCL_##_SOLUTION,其中 ## 代表组编号)。在项目浏览器中,右键单击类
/LRN/CL_S4D401_OOS_INH_USAGE以打开上下文菜单。从上下文菜单中,选择复制....
在包字段中输入包的名称。在名称字段中,输入
ZCL_##_SOLUTION,其中 ## 代表组编号。选择下一步。
确认传输请求并选择完成。
激活复制。
按
Ctrl + F3激活类。
任务 2: 定义接口
定义局部接口(建议名称:LIF_OUTPUT)并在局部类 LCL_FLIGHT 和 LCL_CARRIER 中实施。
注意
暂时将接口留空。我们将在下一任务中添加接口组件。
步骤
在全局类中,导航到本地类
LCL_FLIGHT的定义。例如,在 大纲 视图上选择类名称。
在公共部分,添加声明实现尚不存在的接口
LIF_OUTPUT的语句。如下调整代码:
CLASS lcl_flight DEFINITION ABSTRACT.
PUBLIC SECTION.
INTERFACES lif_output.
使用快速修复将接口
LIF_OUTPUT创建为本地接口。在 INTERFACES 语句中,将光标放在
lif_output上,然后按Ctrl + 1调用可用的快速修复。从可用快速修复列表中,选择创建本地接口 lif_output。
结果
快速修复会生成以下代码:
INTERFACE lif_output.
ENDINTERFACE.
也可以在本地类
LCL_CARRIER中实施新接口。导航到本地类
LCL_CARRIER的定义。在 PUBLIC SECTION 语句下方添加以下代码:
INTERFACES lif_output.
任务 3: 实施接口方法
将实例方法 GET_OUTPUT 的定义从类 LCL_CARRIER 移动到接口 LIF_OUTPUT。然后在本地类 LCL_FLIGHT 中实施接口,在其中将请求委托给方法 GET_DESCRIPTION。
步骤
使用快速修复将(拉取)方法
GET_OUTPUT从本地类LCL_CARRIER移动到本地接口LIF_OUTPUT。
注意
忽略有关方法引用该类的其它组件的警告。
在局部类
LCL_CARRIER中,导航到实例方法GET_OUTPUT的定义。在 METHODS 语句中,将光标置于
get_output上并按Ctrl + 1调用可用的快速修复。从可用快速修复列表中,选择 Pull-Up get_output 到接口 lif_output。
仔细阅读警告,然后选择 继续 。
结果
快速修复将从 LCL_CARRIER 类中删除 GET_OUTPUT 方法的定义,并将该方法添加到接口:
INTERFACE lif_output.
METHODS get_output
RETURNING VALUE(r_result) TYPE tt_output.
ENDINTERFACE.
此外, LCL_CARRIER 类的实施部分中的方法名称已调整为接口方法的完全限定名称:
METHOD lif_output~get_output.
APPEND |{ 'Carrier Name:'(001) } { me->name }| TO r_result.
APPEND |{ 'Passenger Flights:'(002) } { pf_count }| TO r_result.
APPEND |{ 'Average free seats:'(003) } { get_average_free_seats( ) }| TO r_result.
APPEND |{ 'Cargo Flights:'(004) } { cf_count }| TO r_result.
ENDMETHOD.
最后,快速修复在 LCL_CARRIER 类的公共部分为接口方法 lif_output~get_output 创建别名 get_ output:
ALIASES: get_output FOR lif_output~get_output.
在 问题 视图中分析新的语法错误。
打开位于编辑器下方的 问题 视图。
使用快速辅助将类型
TT_OUTPUT和T_OUTPUT从本地类LCL_CARRIER移动到接口LIF_OUTPUT。在局部类
LCL_CARRIER中,导航到类型TT_OUTPUT的定义。在 TYPES 语句中,将光标放在
tt_output上,然后按Ctrl + 1调用可用的快速修复。从可用快速修复列表中,选择 Pull-Up tt_output 到接口 lif_output。
选择继续以忽略与类型
T_OUTPUT相关的警告。重复上述步骤以将类型
T_OUTPUT拉取到接口。如有必要,在接口定义中调整类型
TT_OUTPUT和T_OUTPUT的顺序。接口定义应如下所示:
INTERFACE lif_output.
TYPES t_output TYPE string.
TYPES tt_output TYPE STANDARD TABLE OF t_output
WITH NON-UNIQUE DEFAULT KEY.
METHODS get_output
RETURNING
VALUE(r_result) TYPE tt_output.
ENDINTERFACE.
使用快速修复在本地类
LCL_FLIGHT中添加接口方法GET_OUTPUT的缺失实施。导航到本地类
LCL_FLIGHT的定义。在 INTERFACES 语句中,将光标置于
lif_output上并按Ctrl + 1。或者,选择代码行左侧带有灯泡的错误图标。从快速修复列表中,选择添加实施 get_output。
在添加的方法
lif_output~get_output中,执行实例方法get_description的调用并将结果存储在返回参数r_result中。如下调整代码:
METHOD lif_output~get_output.
r_result = get_description( ).
ENDMETHOD.
以控制台应用形式激活并测试全局类。
按
Ctrl + F3。按
F9。