创建类的实例

学习目标

  • 创建 ABAP 类的实例。

实例创建

您使用相同类型的属性,如普通变量。但是,在类之外,属性名称不足以明确标识属性。要处理类之外的静态属性,首先键入类名称,然后键入静态组件选择器 (=>),然后是属性名称。静态部件选择器是一个双箭头,由等号和大于号组成。

提示

在部件选择器之前或之后不允许使用空格。

对于实例属性,情况更加复杂:要访问实例组件,您需要参考变量。

参考变量是用于创建、寻址和管理对象的特殊类型的变量。参考变量用于指向程序内存中的类实例。使用 DATA 语句声明参考变量,其中附加项 TYPE REF TO 后跟类名称。

引用变量的初始值称为 NULL 引用;引用尚未指向任何位置。

要创建类的新实例,请使用 NEW 运算符。上面的示例使用值赋值右侧的 NEW #( ) 表达式。表达式的结果是新创建 实例的内存地址。然后将此参考存储在分配左侧的参考变量中。

您可能已经注意到,要实例化的类名不会出现在表达式中的任何位置。但是,从 NEW #( ) 表达式的位置,系统已经知道目标变量连接的类型为 REF TO lcl_connection,因此知道它应该创建类 lcl_connection 的实例。NEW 运算符后的井号表示"在等号前使用变量的类型"。(在更高级的场景中,您可以实际指定类名称代替井号)。

提示

括号中必须至少有一个空格。

首次寻址类(可以是访问静态组件或创建类的实例)时,运行时系统也会将类定义加载到程序内存中。此类定义包含所有静态属性,这些属性在类中仅存在一次,而不是针对每个实例存在一次。

使用类名和静态组件选择器处理静态组件。这不适用于实例组件,因为您必须指定要访问的实例。

要处理类之外的实例属性,首先键入参考变量,然后输入实例组件选择器 (->),然后是属性名称。实例组件选择器是由短划线和大于号组成的箭头。

注意

与许多其他编程语言不同,ABAP 对实例组件选择器和静态组件选择器使用不同的字符。

面向对象的编程的主要特征之一是,您可以创建同一类的多个实例。每个实例在程序内存的不同位置创建,并且一个实例中实例属性的值与其他实例中的值无关。但如图所示,同一类的实例共享静态属性的值。

如果将一个参考变量分配给另一个参考变量,系统会将第一个变量指向的对象的地址复制到第二个参考变量。其结果是您有两个指向同一对象的参考变量。

您可以使用相同的参考变量来创建类的多个实例。每次使用 NEW #() 表达式时,系统都会创建类的新实例并将新实例的地址放入参考变量中。但是,新实例的地址将覆盖先前实例的地址。

在上面的示例中,lcl_connection (2) 的地址覆盖 lcl_connection (1) 的地址。因此,程序中不再存在指向 lcl_connection (1) 的参考变量。当实例发生这种情况时,将无法再通过程序对其进行寻址。

为防止程序内存填充了无法再寻址并最终溢出的对象,运行时系统具有称为垃圾收集器的组件。垃圾收集器是一个定期运行的程序,用于查找和销毁不再有参考点的对象。如果在程序期间通过覆盖对象或使用 CLEAR 语句删除对象的最后参考,则垃圾收集器将在下次传输时销毁该对象。

注意

程序结束时,当释放所有参考变量时,垃圾收集器将销毁它们指向的所有实例。您不必担心程序中的资源管理。

如何创建 ABAP 类的实例

演示观看演示(SAP 官方交互式练习)

内部表中的实例管理

一种可以保持对象处于活动状态的方式,是将参考置于内部表中。如果要创建整个对象系列,则最好使用此技术。它使您能够使用单个参考变量创建大量对象。尽管引用变量被下一个对象的地址覆盖,但现有对象是安全的,因为内部表包含对它们的引用。因此,从不删除对象的"最后一个"参考。

如何管理内部表中的实例

演示观看演示(SAP 官方交互式练习)

创建和管理实例

在本练习中,您将创建和管理本地类的实例。

模板:

  • /LRN/CL_S4D400_CLS_LOCAL_CLASS(全局类)

解决方案:

  • /LRN/CL_S4D400_CLS_INSTANCES(全局类)

任务 1: 复制模板(可选)

复制模板类。如果您已完成上一练习,则可以跳过此任务并继续编辑类 ZCL_##_LOCAL_CLASS

步骤

  1. 在 ABAP 编辑器中打开全局类 /LRN/CL_S4D400_CLS_LOCAL_CLASS 的源代码。

  2. Eclipse 工具栏中,选择打开 ABAP 开发对象。或者,按 Ctrl + Shift + A

  3. 输入 /LRN/CL_S4D400_CLS 作为搜索字符串。

  4. 从开发对象列表中选择 /LRN/CL_S4D400_CLS_LOCAL_CLASS然后选择确定

  5. 将项目浏览器视图与编辑器链接。

  6. 在项目浏览器工具栏中,找到与编辑器链接按钮。如果尚未按下,请选择它。因此,应在项目浏览器中突出显示在编辑器中打开的开发对象。

  7. 将类 /LRN/CL_S4D400_CLS_LOCAL_CLASS 复制到您自己的包中的类(建议名称:ZCL_##_INSTANCES,其中 ## 代表组编号)。

  8. 在项目浏览器视图中,右键单击类 /LRN/CL_S4D400_CLS_LOCAL_CLASS 以打开内容菜单。

  9. 从上下文菜单中,选择复制 ....

  10. 在包字段中输入的名称。在名称字段中,输入名称 ZCL_##_INSTANCES,其中 ## 代表组编号。

  11. 调整描述,然后选择下一步

  12. 确认传输请求并选择完成

任务 2: 创建 实例

在全局类**的主**方法中,声明参考变量并创建局部类的实例。

步骤

  1. 在全局类的方法 if_oo_adt_classrun~main 中,声明一个参考变量(建议名称:connection),然后使用局部类 lcl_connection 键入该变量。

  2. 切换到全局类标签。

  3. 如下调整代码:

METHOD if_oo_adt_classrun~main.
DATA connection TYPE REF TO lcl_connection.
ENDMETHOD.
  1. 创建 类的实例并设置属性 carrier_idconnection_id(建议值:LH 表示属性 carrier_id0400 表示属性 connection_id)。

  2. 如下调整代码:

DATA connection TYPE REF TO lcl_connection.
connection = new #( ).
connection->carrier_id    = 'LH'.
connection->connection_id = '0400'.

提示

键入组件选择器 (->) 后,按 Strg + 空格从建议列表中选择属性名称。

  1. 激活类并使用调试器逐步分析发生的情况。

  2. Ctrl + F3 激活类。

  3. 双击行 connection = new #( ).旁的编辑器左边距以设置断点。

  4. F9 键运行类。

  5. 双击单词 connection 以显示参考变量**连接的**内容。

  6. F5 在调试器中进一步执行。检查**连接** 的值是否已更改。

  7. 变量视图中,展开分支**连接**以显示类的初始属性。

  8. F5 在调试器中进一步执行。检查 carrier_id 的值是否已更改。

  9. 再次按 F5。检查 Connection_ID 的值是否已更改。

任务 3: 管理多个实例

创建本地类的更多实例,并将对这些实例的引用存储在内部表中。

步骤

  1. 在全局类的方法 if_oo_adt_classrun~main() 中,声明行类型为 REF TO lcl_connection 的内部表(建议名称:连接)。

  2. 如下调整代码:

DATA connection TYPE REF TO lcl_connection.
DATA connections TYPE TABLE OF REF TO lcl_connection.
connection = new #( ).
connection->carrier_id    = 'LH'.
connection->connection_id = '0400'.
  1. 实例化 类并设置属性后,将对象引用附加到内部表。

  2. 如下调整代码:

connection = NEW #( ).
connection->carrier_id = 'LH'.
connection->connection_id = '0400'.
APPEND connection TO connections.
  1. 再创建两个类 lcl_connection 的实例,将其实例属性设置为与第一个实例不同的值,并将新实例的引用附加到内部表**连接。对所有三个实例使用相同的参考变量连接**。

  2. 如下调整代码:

connection = NEW #(  ).
connection->carrier_id    = 'LH'.
connection->connection_id = '0400'.
APPEND connection TO connections.
connection = NEW #(  ).
connection->carrier_id    = 'AA'.
connection->connection_id = '0017'.
APPEND connection TO connections.
connection = NEW #(  ).
connection->carrier_id    = 'SQ'.
connection->connection_id = '0001'.
APPEND connection TO connections.
  1. 激活类并使用调试器逐步分析发生的情况。

  2. Ctrl + F3 激活类。

  3. 双击第一行 connection = new #( ).旁的编辑器左边距以移除断点。

  4. 双击第一行 APPEND connection TO connections.旁的编辑器左侧边距,设置新的断点。

  5. F9 键运行类。

  6. 双击单词 connection 以显示参考变量**连接的**内容。

  7. 双击单词 connections 以显示内部表**连接的**内容。

  8. F5 在调试器中进一步执行。检查**连接**的内容是否已更改。

  9. 变量视图中,展开分支**连接**以显示内部表的内容。

  10. 多次按 F5,直到程序结束。执行此操作时,请检查内部表的内容。

  11. 全局类标签上的代码与模型解决方案的以下提取内容进行比较:

METHOD if_oo_adt_classrun~main.
DATA connection TYPE REF TO lcl_connection.
DATA connections TYPE TABLE OF REF TO lcl_connection.
* First Instance
**********************************************************************
connection = NEW #(  ).
connection->carrier_id    = 'LH'.
connection->connection_id = '0400'.
APPEND connection TO connections.
* Second Instance
**********************************************************************
connection = NEW #(  ).
connection->carrier_id    = 'AA'.
connection->connection_id = '0017'.
APPEND connection TO connections.
* Third Instance
**********************************************************************
connection = NEW #(  ).
connection->carrier_id    = 'SQ'.
connection->connection_id = '0001'.
APPEND connection TO connections.
ENDMETHOD.