After completing this lesson, you will be able to:
After completing this lesson, you will be able to:
Create Instances of an ABAP Class
Create Instances
You work with attributes like normal variables of the same type. Outside the class, however, the attribute name is not sufficient to identify the attribute unambiguously. To address a static attribute outside the class, first type the class name, then the static component selector (=>), and only then the attribute name. The static component selector is a double arrow made up of an equals sign and the greater than sign.
Hint
No blanks are allowed before or after the component selector.
For instance attributes the situation is even more complicated: In order to access an instance component, you need a reference variable.
A reference variable is a special kind of variable that you use to create, address, and manage an object. A reference variable is used to point at the instance of a class in the program memory. You declare reference variables using the DATA statement with the addition TYPE REF TO followed by the name of a class.
The initial value of a reference variable is called the NULL reference; the reference does not yet point anywhere.
To create a new instance of a class, you use the NEW operator. The example above, uses a NEW #( ) expression on the right hand side of a value assignment. The result of the expression is the memory address of the newly created instance. This reference is then stored in the reference variable on the left-hand side of the assignment.
You may have noticed that the name of the class that you want to instantiate does not appear anywhere in the expression. However, from the location of the NEW #( ) expression, the system already knows that the target variable connection has the type REF TO lcl_connection, and consequently it knows that it should create an instance of the class lcl_connection. The pound sign after the NEW operator means "use the type of the variable before the equals sign". (In more advanced scenarios, you can actually specify the name of the class in place of the pound sign).
Hint
There must be at least one blank between the brackets.
When you address a class for the first time (which could be accessing a static component or creating an instance of the class), the runtime system also loads the class definition into the program memory. This class definition contains all of the static attributes, which only exist once in the class instead of once for each instance.
You address static components using the class name and the static component selector. This does not work for instance components because you have to specify the instance you want to access.
To address an instance attribute outside the class, first type the reference variable, then the instance component selector (->), and only then the attribute name. The instance component selector is an arrow made up of a dash and the greater than sign.
Note
Unlike many other programming languages, ABAP uses different characters for instance component selector and static component selector.
One of the main characteristics of object oriented programming is the fact that you can create multiple instances of the same class. Each instance is created in a different place in the program memory and the values of instance attributes in one instance are independent from the values in other instances. But as the graphic illustrates, instances of the same class share the value for the static attributes.
If you assign one reference variable to another, the system copies the address of the object to which the first variable is pointing into the second reference variable. The result of this is that you have two reference variables that point to the same object.
You can use the same reference variable to create more than one instance of a class. Each time you use the NEW #( ) expression, the system creates a new instance of the class and places the address of the new instance into the reference variable. However, the address of the new instance overwrites the address of the previous instance.
In the example above, the address of lcl_connection (2) overwrites the address of lcl_connection (1). Consequently, there is no longer a reference variable in the program pointing to lcl_connection (1). When this happens to an instance, it can no longer be addressed from the program.
To prevent the program memory from becoming filled with objects that can no longer be addressed and eventually overflowing, the runtime system has a component called the garbage collector. The garbage collector is a program that runs periodically to look for and destroy objects to which no more references point. If during a program you delete the last reference to an object by overwriting it or using the CLEAR statement, the garbage collector will destroy the object on its next pass.
Note
At the end of a program, when all of the reference variables are freed, the garbage collector will destroy all of the instances to which they had pointed. You do not have to worry about resource management in the program yourself.
One way in which you can keep objects alive is to place the references into an internal table. This is a technique that you may well want to use if you are creating a whole series of objects. It enables you to use a single reference variable to create lots of objects. Although the reference variable is overwritten with the address of the next object, the existing objects are safe because the internal table contains a reference to them. You therefore never delete the "last" reference to the objects.
If you finished the previous exercise Define a Local Class, create a copy of your global class ZCL_##_LOCAL_CLASS, and name the copy ZCL_##_INSTANCES, where ## is your group number. Then skip the rest of this task.
In the Project Explorer view on the left, expand your package.
Expand node Source Code Library → Classes
Right-click the name of the class you want to copy and choose Duplicate.
In the Name field, enter the name ZCL_##_INSTANCES, where ## is your group number.
Choose Next.
Select your transport request and choose Finish.
If you did not finish the previous exercise, create a new global class ZCL_##_INSTANCES, where ## is your group number. Ensure that the class implements the interface IF_OO_ADT_CLASSRUN.
Choose File → New → ABAP Class.
Enter the name of your package in the Package field. In the Name field, enter the name ZCL_##_INSTANCES, where ## is your group number. Enter a description.
In the Interfaces group box, choose Add.
Enter IF_OO_ADT_CLASSRUN. When the interface appears in the hit list, double-click it to add it to the class definition.
Choose Next.
Select your transport request and choose Finish.
Copy the following code to the Local Types tab:
Code snippet
CLASS lcl_connection DEFINITION.
PUBLIC SECTION.
DATA carrier_id TYPE /dmo/carrier_id.
DATA connection_id TYPE /DMO/Connection_id.
CLASS-DATA conn_counter TYPE i.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS lcl_connection IMPLEMENTATION.
ENDCLASS.
Create an instance of the class and set the attributes carrier_id and connection_id (Suggested values: "LH" for attribute carrier_id and "0400"for attribute connection_id.
Add the following code to your class after the DATA statement:
After typing the component selector (->), press Strg + Space to choose the attribute names from a suggestion list.
Activate the class and use the Debugger to analyze step by step what happens.
Press Ctrl + F3 to activate the class.
Double-click the left-hand margin of the editor next to the line connection = new #( ).to set a break point.
Press F9 to run the class.
Double-click the word connection to display the content of reference variable connection.
Press F5 to go one step further in the debugger. Check that the value of connection has changed.
In the Variablesview, expand the branch connection to display the initial attributes of the class.
Press F5 to go one step further in the debugger. Check that the value of carrier_id has changed.
Press F5 again. Check that the value of Connection_ID has changed.
Task 3: Manage Several Instances
Steps
In method if_oo_adt_classrun~main( ) of your global class, declare an internal table with the line type TYPE REF TO lcl_connection.
Between METHOD if_oo_adt_classrun~main. and ENDMETHOD., under the existing DATA statement, enter the following: DATA connections TYPE TABLE OF REF TO lcl_connection..
After instantiating the class and setting the attributes, append the object reference to the internal table.
Change your code so that it looks like this:
Code snippet
connection = NEW #( ).
connection->carrier_id = 'LH'.
connection->connection_id = '0400'.
APPEND connection TO connections.
Create two more instances of class lcl_connection, set their instance attributes to different values as in the first instance and append the references to the new instances to internal table connections. Use the same reference variable connection for all three instances.
Before ENDMETHOD., add the following code:
Code snippet
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.