Вы находитесь на странице: 1из 334

What Is ABAP?

ABAP stands for Advanced Business Application Programming. ABAP is a


programming language that was developed by SAP for developing commercial
applications in SAP environment.

The development process of ABAP went through the following evolutionary stages:

• In early days (1970s) ABAP stood for “Allgemeiner Berichts-Aufbereitungs


Prozessor” (Generic Report Generation Processor). That time ABAP was
implemented as a macro assembler under R/2 and exclusively used for creating
reports.

• In mid 1980s, ABAP had become an interpreted language and was powerful
enough to be used to create business application programs, in particular to
program dialog-controlled transactions.

• In early 1990s, the SAP R/3 system was born and ABAP become ABAP/4, that
ABAP 4GL (4th Generation Programming Language). It now formed the technical
and software basis of the entire SAP System. Apart from system core which is
written in C, all SAP application modules, R/3 Basis System and the development
environment were now created in ABAP/4.

• At the end of 1990s, ABAP is extended with object oriented programming


constructs and from this point on, the language was known as ABAP Objects.

• In the beginning of 2000s ABAP programs were made Unicode-Compatible in


order to support the internationalization of the SAP System.

• With SAP technology platform under the name “SAP NetWeaver”, ABAP
become the programming interface of the SAP NetWeaver Application Server
ABAP (AS ABAP).

1
What is SAP NetWeaver?
SAP NetWeaver is SAP's (Systems Applications and Products in Data Processing)
technological platform (Components, Tools and Applications) which provides a runtime
and development environment for all SAP applications.

SAP NetWeaver is the fully interoperable Web-based cross-application platform that can
be used to develop not only SAP applications but others as well. It allows a developer to
integrate information and processes from geographically dispersed locations using
diverse technologies, including Microsoft's .NET, IBM's WebSphere, and Sun's Java
technologies.

SAP NetWeaver is based on Structure Oriented Architecture (SOA). SOA define


methods for systems development and integration where systems provide functionality as
interoperable services. The concept of a service, specifically a Web service -- is a key
part of the SOA. A Web Service is defined by the W3C as "a software system designed to
support interoperable machine-to-machine interaction over a network". Loose coupling
(no service is tightly attached to a single system), Interoperability and Portability define
the ground rules for development, maintenance, and usage of the SOA.

Enterprise SOA (eSOA) is the term SAP gives to its own SOA tools and technologies.

SAP NetWeaver platform comprises of the following components, tools and applications:

2
Components:

• Application Server: Supports platform-independent Web services, business


applications, and standards-based development

• Business Warehouse: Integrate data from across the enterprise and transform it
into information to drive sound decision making.

• Business Process Management: Provides tools to help you model, execute, and
monitor business processes based on a single, consistent process model.

• Process Integration: Delivers SOA-based technology that supports application-


to-application (A2A) and business-to-business (B2B) integration, and to
accelerate composite application development.

• Master Data Management: Ensures cross-system data consistency and a single


version of master data for supplier, product, customer, or user-defined data
objects in heterogeneous environments.

• SAP NetWeaver Mobile: Provides a mobile runtime environment based on open


and flexible technology standards and a powerful development environment for
building integrated mobile solutions with native or browser-based user interfaces.

• SAP NetWeaver Portal: Unifies critical information and applications to give


users role-based views that span the enterprise, enabling you to take full
advantage of your information resources.

• SAP Auto-ID Infrastructure: Gives you all the capabilities you need to integrate
all automated sensing devices – including RFID (Radio Frequency Identification)
technology electronically captures, stores, and transmits data readers and printers,
Bluetooth devices, embedded systems, and bar-code devices.

• Identity Management: Helps companies manage users' access to applications


securely and efficiently, while meeting audit and compliance requirements.

• Information Lifecycle Management: Enables companies to decommission


redundant SAP system while preserving full auditing and reporting capabilities
for stored data.

Tools:

• Adaptive Computing Controller: Provides a central point of control for


assigning computing resources and optimizing their use.

3
• Composition Environment: Provides a robust environment for design,
deployment, and running of composite applications that comply with a service-
oriented architecture.

• Developer Studio: Offers a convenient user interface and rich functionality for
developing J2EE applications.

• Visual Composer: Allows composing model-based business applications in a


flexible way, without manual coding.

• SAP Solution Manager: Application management solution facilitates technical


support for distributed systems.

Applications

• Enterprise Search: Helps business users navigate critical business information


by enabling seamless, secure access to SAP and non-SAP information and
processes.

• Duet: Enables seamless access to SAP business processes and data via Microsoft
Office.

• Alloy: Simplifies interaction with people, processes, and information by


providing intuitive access to SAP software and information via the familiar IBM
Lotus Notes.

• SAP Central Process Scheduling application by Redwoods: Helps companies


manage, monitor, and execute business-critical processes from a central location
by delivering adaptive, real-time, event-driven job scheduling and process-
automation capabilities across distributed and heterogeneous platforms.

• Enterprise Modeling Applications by IDS Scheer: Deliver Web-based


components that support the process life cycle for business process design,
analysis, optimization, and implementation.

4
Another way of defining SAP NetWeaver.
SAP NetWeaver is a set of capabilities that are provided by different SAP products
constructed to work with each other to make applications work together, build new
applications on top of existing applications and lower the Total Cost of Ownership
(TCO). TCO is about all the different expenses involved in owning and running an
enterprise application.

The figure above depicts that the core capabilities of SAP NetWeaver are consists of the
following four layers:

• People Integration
• Information Integration
• Process Integration
• Application Platform

5
People Integration
People Integration means to bring people together and help them work more efficiently.
Information Integration means to bring information from different locations and have it
make sense in the context what a user do everyday.

Process Integration
Processes Integration means coordinating the flow of work across departments, divisions
and between companies.

Application Platform
Application Platform is called the SAP Application Server (SAP AS). SAP AS is
foundation for the entire SAP software stack. It is the engine behind the scene of SAP
NetWeaver that drives all SAP’s Applications and Tools. It provides a platform for
NetWeaver components (Enterprise Portal etc.) and ABAP and Java applications.

Composite Application Framework


Composite Application Framework (SAP CAF) is modeling and development
environment for creating composite applications. Composite applications are applications
built out of services provided by other applications.

Life Cycle Management


The SAP Lifecycle Management (SAP LM) offers all the functionality needed for
integrated product and asset management like Program and project management and
Quality management.

6
SAP Application Server
SAP Application Server (SAP AS) is foundation for the entire SAP software stack. It is
the engine behind the scene of SAP NetWeaver that drives all SAP’s Applications and
Tools. It provides a platform for NetWeaver components (Enterprise Portal etc).

SAP systems are used for mapping business processes or business applications. These
applications should be implemented independent of the hardware environment used
(operating system, database) to the greatest extent possible. For this, the SAP Application
Server provides two runtime environments: the ABAP runtime environment (AS ABAP)
and a Java runtime environment (AS JAVA). Both application servers work on different
data (different database schemas) and are linked together by allowing mutual access
through the Java Connector (JCo).

Application Server ABAP


The Application Server ABAP provides the ABAP runtime environment that is a virtual
machine for ABAP programs independent of the hardware, operating system and data
base system. Figure below shows a simplified overview of the main AS ABAP
components.

AS ABAP can be used by user or by software, including the remaining components of


SAP NetWeaver. User can access it using user interfaces that are available in the form of

7
web browser or SAP GUIs installed on desktop PCs. Software components generally
access it through the network, for which two protocols are used: HTTP/HTTPS/SMTP
for Internet connections and SAP’s own Remote Function Call (RFC) protocol for calling
ABAP functionality through any external clients.

The components of AS ABAP can be divided according to their tasks into three layers of
a client-server system:

• Presentation Layer
• Application Layer
• Persistence Layer

Presentation Layer

The components of the presentation layer are responsible for the presentation of data to
users and the receiving of user entries. User interfaces for AS ABAP include commercial
web browsers and SAP’s SAP GUI.

When web browsers are used in application programs, HTML pages prepared in the
presentation layer are accessed. Application program access these HTLML pages through
the Internet Connection Framework (ICF). The ICF uses standard protocols (HTTP,
HTTPS, and SMTP) to operate communications between systems through the Internet.
Presentation in a web browser is based on Web Dynpro and Business Server Pages
(BSP).

SAP GUI is the graphical user interface that runs on a Microsoft Windows, Apple
Macintosh or UNIX desktop. The Control Framework (CFW) supports controls (ActiveX
and JavaBeans) that are implemented within the SAP GUI, depending on the version of
SAP GUI currently in use. The presentation in the SAP GUI is based on the classical
dynpro technology.

Web Dynpro ABAP

Web Dynpro for ABAP (WD4A, WDA) is the SAP standard UI technology for
developing Web applications in the ABAP environment. It consists of a runtime
environment and a graphical development environment with special Web Dynpro tools
that are integrated in the ABAP Workbench. Web Dynpro is based on Model View
Controller (MVC). MVC is an architectural pattern used in software engineering. The
pattern isolates business logic from input and presentation, permitting independent
development, testing and maintenance of each.

Business Server Pages

Business Server Pages (BSP) can incorporate server-side scripts written directly in ABAP
or Java Script. It enables direct access to all elements in the application server (such as

8
function modules, database tables, ABAP Objects, and so on.). BSP is similar to Java
Server Page (JSP) as it is coded in HTML of AS ABAP Internet applications. BSPs
represent the predecessor technology of Web Dynpro ABAP. BSP also supports MVC,
but is not a prerequisite.

Dynpro

Dynamic program (Dynpro) defines a user interface of an ABAP program in a window of


the SAP GUI. Each dynpro is a component of an ABAP program. The screen of a dynpro
can contain a set of predefined screen elements or GUI controls. In addition to screen, a
dynpro also contains a screen processing logic written in a separate programming
language that is called dialog modules in ABAP program.

User interfaces of new applications should be designed primarily with Web Dynpro
ABAP, even if it is not initially intended to use the system via the Internet.

The ICF and CFW provide services between the application program and presentation
layer.

Application Layer

The application layer is the software layer in which application programs are executed.
The application layer contains a kernel written primarily in C/C++ that servers as a
platform for application programs which is independent from hardware, operating system
and database. The kernel provides processors (virtual machines) for the following
programming languages:

XSLT and ST

XSLT (eXtensible Stylesheet Language Transformation) allows XML formats to be


converted into any other XML format. Simple Transformation (ST) is an SAP-specific
language used to transform ABAP data to XML and vice versa. The XSLT and ST
processors execute XSLT and ST programs. These programs are edited with
Transformation Editor of the ABAP Workbench.

ABAP and ABAP Objects

ABAP and ABAP Objects (OO enhancement to ABAP) is the programming interface of
AS ABAP for business management applications. The corresponding ABAP processor
accounts for the largest part of the AS ABAP kernel. ABAP programs are created with
the ABAP Editor, which can be used either as an independent application or as an add-on
to other tools such as Object Navigator or Class Builder.

9
Java Script

JavaScript programs are executed by JavaScript processor. Variables of the script can be
linked to data objects of an ABAP program. Use of JavaScript on AS ABAP has
negligible significance. There is no dedicated editor for JavaScript programs in the
ABAP Workbench; the CL_JAVA_SCRIPT system class provides an interface to the
JavaScript Engine.

Object Services

Object Services provide global services, which ABAP Objects language elements cannot
provide themselves, to applications written in ABAP Objects. These Object Services
include: A Persistence Service, A Transaction Service, and A Query Service.

Persistence Layer

The persistence layer is the software layer in which persistence data is held in a database.
Each AS ABAP accesses a central database on which its entire dataset is stored. This
means that not only the application types, but also all administrative data, customizing
settings and ABAP source codes.

The central database can be accessed by ABAP programs through the database interface
of AS ABAP. This interface makes AS ABAP independent from the database system that
is actually used. The database interface is subdivided into an Open SQL interface and
SQL interface.

Open SQL is a sunset of SQL realized by ABAP statements and includes the Data
Manipulation Language (DML) portion. The statements of Open SQL access the AS
ABAP database through the Open SQL interface, irrespective of the platform. The Open
SQL interface converts the Open SQL statements into manufacturer specific SQL and
passes it onto the DBMS. With Open SQL you can read (SELECT) and change
(INSERT, UPDATE, MODIFY, DELETE) data in database tables that are defined in
the ABAP Dictionary. Only the statements from Open SQL should be used in application
programs.

Native SQL interface passes on the manufacturer-specific SQL statements, unchanged to


the DBMS. Native SQL refers to statements that can be executed in ABAP programs
between EXEC SQL and ENDEXEC statements.

Communication Components

Communication components are position somewhat aside from the three layers:

Inter Communication Manager

10
Internet Communication Manager (ICM) is a process in ABAP kernel that allows it to
communicate directly with the Internet via HTTP/HTTPS/SMTP. ICM allows connection
to web based presentation components such as Web Dynpro ABAP and BSP. It also
enables and AS ABAP to act both as a client and as a server for Web Services. ABAP
program access the ICM through the classes and interfaces of the Internet
Communication Framework (ICF).

Remote Function Call Interface

Remote Function Call (RFC) is an invocation of a function that is located in a different


system than the one in which the calling program is running. Calls are possible between
different AS ABAPs, or between an AS ABAP and external system.

11
AS ABAP Processes
The SAP runtime system consists of a number of parallel processes that work together.
The following graphic illustrates the most important processes of application server
ABAP.

AS ABAP Processes

In addition to several work processes whose number and type are determined at the
startup of AS ABAP, each ABAP application server contains a dispatcher, a gateway,
ICM and a message server.

Dispatcher

The dispatcher is the link between the work processes and the users logged onto the
ABAP application server (that is, the SAP GUIs of the users). Its task is to receive
requests from the SAP GUI and direct them to a free work process. In the same way, it
directs screen output back to the appropriate user. If all the work processes are occupied
the requests are stored in the dispatcher queue.

Work Processes

Work processes are software components that execute an application. Each work process
is linked to a memory area containing the context of the application being run. The
context contains the current data for the application program. There are the following
types of work process:

12
• Dialog: Fulfill all requests for the execution of dialog steps triggered by an active
user. Every dispatcher requires at least two dialog work processes.
• Update: Execute update requests. At least one update work process per SAP
system and you can have more than one per dispatcher.
• Background (batch): Execute programs that run without interacting with the user.
You need at least two background work processes for each SAP system. You can
configure more than one background work process for each dispatcher.
• Enqueue: Administers the lock table in the shared memory. The lock table
contains the logical database locks of the ABAP stack of the SAP system. Only
one enqueue work process is needed for each system.
• Spool: Pass sequential data flows on to printers. Every SAP system requires at
least one spool work process; you can also have more than one spool work
process per dispatcher.

Internet Communication Manager

The Internet Communication Manager (ICM) enables SAP systems to communicate


directly with the Internet. The ICM receives requests from the Internet and forwards them
to the SAP system for processing. It can also direct HTTP requests from an SAP system
to a Web server and send the response back to the SAP system. You can configure a
maximum of one ICM process per application server. Memory Pipes are memory-based
communication objects that are used to transfer data between the ICM and the work
processes.

Message Server

The message server (MS) handles the communication between the distributed dispatchers
within the ABAP stack of an SAP system, thereby enabling scalability of several parallel
application servers. The message server is configured only once per SAP system.

Gateway

The gateway (GW) enables communication through RFC interface between SAP
systems, or between SAP systems and external application systems. There is one per
dispatcher.

13
Memory Organization of AS ABAP
AS ABAP is the system in which an ABAP programs runs. From software point of view,
the application layer of an AS ABAP is spread across at least one, but usually several,
application servers. If an AS ABAP has several application servers, they are usually also
installed on several machines, whose operating systems don’t have to be identical.
Therefore; in application layer there is Message Server (MS) that is responsible for
communication between the application servers.

Each application server provides a range of services of operating the AS ABAP. The
services of an application server are implemented by work processes, whose number and
types are set when the AS ABAP is started. Work processes are software components that
can execute an application. There are different types of work processes for different
applications: dialog, enqueue, background, spool and update work processes.

Work process is logged on as a user to the database system for the entire runtime of an
AS ABAP. During the ASP ABAP runtime, a database logon can’t be passed on from
one work process to another. SAP Memory Management is used for memory areas of an
application server.

Figure below shows where an ABAP program runs on an application server and what
memory areas it can access here.

14
AS Memory Organization

The memory areas of an application server that can be accessed in an ABAP program are
as follows:

• Shared Memory
• SAP Memory
• ABAP Memory
• Roll Area

Shared Memory
Each application server has its own shared memory. The shared memory is the memory
area that is used by all parts of an application server together. The ABAP runtime
environment uses the shared memory for programs, program data and buffering (from
database in data dictionary in a table buffer). ABAP programs can access shared objects
and data clusters in the shared memory.

SAP Memory
When a dialog user or an external client (via RFC or ICF) logs on to an AS ABAP, it is
connected to an appropriate application server and opens a user session on this AS.

Each user session is assigned its own memory area, the SAP Memory, in which all ABAP
programs of a user session have joint access to SPA/GPA parameter (Used to fill the
input fields of a called transaction with data from the calling program). The
corresponding statements are SET PARAMETER and GET PARAMETER. These
parameters are only suited to saving short character-type fields, such as the name of the
last programs called. The input fields of dynpros can be linked to SPA/GPA parameters
and in order to pre-fill them before a dynpros is called.

ABAP Memory
At least one main session or external mode is opened for each user session. In dialog
processing, a user session can manage up to 16 main sessions, each of which is linked to
separate window. If you execute the function Create New Session in the SAP GUI, or
enter a transaction code behind /o in the input window of standard toolbar, you open a
new main session in a new window. From an ABAP program a new main session can be
open via RFC (CALL FUNCTION STARTING NEW TASK).

Each main session is assigned a separate memory area, known as the ABAP Memory, in
which data clusters can be stored. The data in the ABAP memory is retained during a
sequence of program calls within a call sequence.

15
A call sequence is formed if you can return from called program to the calling program.
This is always the case when you call an ABAP program with SUBMIT AND RETURN
or CALL TRANSACTION. Only programs of a call sequence have common access to
data in the ABAP memory, and this is primarily for data transfer during program calls.
When the first program of a call sequence is terminated, the corresponding ABAP
memory is also released.

Roll Area
With each call via SUBMIT or CALL TRANSACTION or LEAVE TRANSACTION of an
ABAP program in main session, an internal session is opened. A memory area called a
Roll Area is assigned to the internal session, in which the data and objects of an ABAP
program are stored while it is executed. This is the actual memory of an ABAP Program.
With program calls, a maximum of nine internal sessions can be stacked as a call
sequence in a main session. In main session, only the internal session of the program that
is just running exists in am active version. All memory content of previous programs is
saved on the stack.

Technically each internal session is divided into a Program Execution Area (PXA) and a
Roll Area. The PXA is further common memory area of the application server in which
the unchangeable data (bytecodes) of t he programs that are currently running there is
stored. Only the roll area is individually reserved for an internal session and contains its
changeable data.

An internal session will exist for as long as its first program, the main program, is
executed. The additional loaded programs and their data also remain loaded until the end
of the internal session.

All programs of an internal session have joint access to anonymous data objects and
instances of classes created with CREATE. Within internal session, references to objects
can be copied from one program to procedures of another program.

On 64-bit platform, an internal session can theoretically require up to 4TB of memory.


On 32-bit platforms, the theoretical maximum limit is 4GB.

16
ABAP; A Practical Introduction
Change and Transport System (CTS)
The SAP NetWeaver repository is the central place where development components in
the ABAP Workbench are stored. These components include all of the: process models,
data models, business object models, business objects, and all data and their relationships.
The repository also includes the ABAP Dictionary.

The CTS is the central tool for managing changes to repository objects that you make in
the ABAP Workbench. The CTS records all changes in transport/change requests. When
you have finished your work in ABAP Workbench, or have reached a certain stage, you
can release the request. The change request is then used to copy the changes from this
client to other clients or systems. This automatic procedure is known as a transport.
Transports of changes by the CTS allow you to develop in one environment, test your
development work in a test environment, and then, if the tests are successful, use it
productively. This makes sure that productive operations are not placed at risk by faulty
settings or program errors.

CTS enable you to define transport layer as an attribute of a package. The transport layer
refers to the transport path a package should take in a system landscape. The usual
landscape has a least three layers:

The transport layer by itself does not transport anything. You need a transport/change
request to get something transported.

A change request can be created in two ways:

17
1. When you create or modify objects in the ABAP Workbench, a window appears
asking you to assign the object to an existing change request (Own requests) or to
create a new change request (Create request). See Package Creation Topic.
2. Through Transport Organizer (SE09).

Creating a Request in the Transport Organizer:

1. To start application server, follow the path Start -> Programs -> SAP
Netweaver 7.01 ABAP Trial Version -> NSP -> Start Application
Server.Select Create (F6) to create new transport request.

2. Log on as a BCUSER.

18
3. Enter SE09 transaction code in the text field of standard toolbar to open the
Transport Organizer.

4. Select the Create (F6) function from the toolbar of Transport Organizer to
create new transport request.

5. Select Workbench request and click continue.


6. Create Request dialog will appear, enter short description of the change
request. And Click Save.

19
7. This will open up the Display Request Window, where you can see the change
request in hierarchal order. You can use it now during object creations.

20
Packages
Packages are used to organize development objects (programs, tables, screens, BAPIs,
function modules, types, and so on) and handle their connection to the ABAP software
logistics (Change and Transport System). All objects that can be changed using ABAP
Workbench (Repository Objects) are part of package. Every AS ABAP contains a
predefined package named $TMP. $TMP package is used for local practice and test
programs. Every package starting with $ character is considered local and can’t be
transported to other SAP system.

Packages help developers to modularize, encapsulate, and decouple units in the SAP
System. Packages may have the following attributes:

• Nesting: allows to embed packages in other packages. With nesting you can split
up larger units of the SAP System and structure them in a hierarchy.

• Visibility: is a property of package elements. From the outside, a package looks


like a "black box." They are always visible to other elements in the same package
and always invisible to embedded (sub-)packages within their package. For an
element to be visible outside the package, it must be contained in at least one
package interface.

• Use access: is the right of one package to use the visible elements in the interface
of a second package (but not the other way round).

When we create a package, we specify the following properties:

• Package: The name of the package to be created. The name should follow the
customer namespace conventions.
• Description: To define the package.
• Application Component: Determine the location of the package within the
application hierarchy by specifying the corresponding application component.
• Software Component: The software component describes a set of development
objects that can only be delivered in a single unit. For customer developments you
should enter HOME as the software component.
• Transport Layer: The transport layer determines if the objects of this package are
to be transported to a subsequent system and, if so, to which system.
• Package Type: You can choose between three package types:

o Standard package / Not a main Package (Can contain Repository objects


and other packages)
o Main package (Can only contain other packages)
o Structure package (Can only contain main packages)

21
Note: Values like Application / Software component is developed by system administrator
when system is created.

Creating Package

Package can be created in two ways:

a) In the navigation area of Object Navigator (SE80), choose the object type
Package from the object list and enter the name of the package in the input field
below. Choose Enter. If the specified package does not already exist, the system
branches to a dialog for creating a package.

b) Call the package builder (SE21 or SPACKAGE). Enter Package Name and push
Create button.

1. Enter the following properties in Create Package dialog.

a) Package: Z_MyPackage
b) Description: My Training and Demo Programs
c) Application Component: CA (Press F4 for selection and F1 for detail
help).
d) Software Component: Home (Press F4 for selection and F1 for detail
help).
e) Transport Layer: ZNSP (For our demo system you should use the
transport layer ZNSP).
f) Package Type: Not a main Package (since Main Package can’t directly
contain development objects).

22
2. After selecting Save you will be prompted for a transport request.

3. If you have already created transport request, push Own Requests button or select the
Create button to create new one.

4. In new create request dialog enter short description.

Note: In a real-world development project you will always use a transport request
that is created in the Transport Organizer (SE09) and paste this into the dialog with

23
the header Prompt for transportable Workbench Request, if you just need a transport
request without any particular properties, you can do it the way we do it here.

5. Pressing the Save button opens another dialog window and we are done with
transport request.

6. Clicking Continue will bring Package Builder: Change Package Window. Check the
Package Check as Server. This ensures that only objects declared in the package
interface of the package can be addressed from other transportable packages. Click
Save button on standard toolbar and close the Package Builder.

24
Creating Hello World Program in Package
1. Enter SE80 in text field of standard toolbar to open Object Navigator.
2. Select Package from Object List and type Z_MyPackage into text field below and
press return key. You will see that our package is now visible in the Repository
Browser.

3. Right-click on the package Z_MyPackage and choose Create – Program.

4. Enter the name of the program we want to create Z_A_HW. Deselect “With TOP
INCL” (Top Include) because we do not need a top include and confirm.

5. Next dialog shows the properties of the new program. One of the most important
program properties of an ABAP program is its type. From the list provided, we want
to select the type "Executable program" for our simple Hello-World program, and
change or add no other properties. In particular, ensure that the properties "Unicode
checks active" (strict static type checks, separation of byte and character string
processing) and "Fixed point arithmetic" (for decimal numbers the decimal separator
is taken into account in calculations) should always be checked. Logical Databases
option is no more used in ABAP Objects. Press Save button.

25
6. Create Object Directory Entry dialog appears, click save to continue. The Object
Directory is a directory of all the Repository Objects that make up the SAP System.
When you create an object, the corresponding object directory entry is also created.

7. Next dialog prompt for transport request. The transport request our package belongs
to is already in the relevant field. Again Confirm it.

26
8. Next the ABAP Editor is appear, where you write code. Click Yes if you wanted to
check the quick start.

9. To configure the new ABAP Editor go to Utilities  Settings  Front-End Editor


(New).

10. You can also double click the program name to open ABAP Editor.You can see the
framework predefined by the ABAP Workbench. This syntax consists of a few lines
of comments, and also contains an initial statement named Report.

27
11. To change the program. Go to the change mode by pressing the respective button:

Below the report-statement enter:

12. To format the source code. ABAP Editor uses the Pretty Painter. To configure it go to
Utilities  Settings  Pretty Painter. Check Indent and Convert Uppercase
/Lowercase.

13. Click the Pretty Painter button in the ABAP Editor and the format of statements
changes.

28
14. To check the syntactic corrections, select Check from the context menu of the
program name in object list. Or Check button from standard toolbar.

15. The error-free program must be activated. Select Activate function . During The
error-free source code is converted to byte code that is stored in the database. After
activation program will be visible to every user using System  Services 
Reporting.

16. To run the program we press the icon: or Execute  Direct from context menu
of program name or by pressing F8.

17. The expected “Hello World” output appears in a special screen.

Note: ABAP Programs can be executed by two ways. Using the Execute function or
transaction codes (SA38 and SE38). SA38 can be used only to execute or run a program.
It is more recommended to use by Functional Consultants/Users of the program to reduce
the risk of mistakenly modification or deletion of the program. SE38 is use to display an
ABAP Editor screen where transaction is not limited only to program execution but also
to display or modify the program code. SA38 can be used also by ABAPers to execute
the program. Also to call the program from other program the use the SUBMIT ….

29
statement. With addition AND RETURN specify the system returns to the caller after the
called program is terminated.

SA38 Call

SE38 Call

ABAP programs can also be called through transaction codes (transaction maintenance
SE93). To call transactions from other program use the statement CALL
TRANSACTION …. and to abort the calling transaction use LEAVE TRANSACTION.

18. To display the “Hello World“ is message box change the code to:

30
As a result a dialog window greets the world. Instead of ’I’ try E, X for type message.

Output with Type ‘I’

Output with Type ‘E’, message will be shown in status bar

Dissecting the Hello World Program

ABAP program consists of statements. Statements are composed of tokens and


terminated by Period (.). Tokens must be separated by at least one space. Possible tokens
include Keywords, Operands, Operators and Special Characters. In our example
REPORT is the keyword and ZAHWP is the operand. ABAP keyword determines the
category of the statement. (e.g. Modularization, Control, Call and Operational
Statements).

31
Every standalone ABAP program, that is, all types of programs except for so-called
include programs, start with an introductory statement. In our first program, the
introductory statement is REPORT. The REPORT keyword expresses the fact that
historically executable program was once exclusively used for reporting.

After the introductory statement, every ABAP program follows a fixed program structure
that divides it into two parts:

a) Global Declaration part


b) Procedural part

Global declaration part directly follows the introductory statement. Declarative


statements can be used for definitions and declarations, which will be visible and
applicable throughout the entire ABAP program. Examples of objects that can be
declared or defined here are data types, classes, interfaces, data objects and screens. For
larger programs, these declarations are generally made in a special include program, the
"top include," which is supported by the ABAP Workbench and inserted at this position.

The DATA statement declares a data object msg of type string and initializes it to a start
value “Hello World“.

After the global declaration part comes the procedural also known as implementation
part, in which the actual processing logic of the ABAP program is implemented. The
implementation part is divided into individual procedural units that are referred to as
Processing Blocks. Every ABAP statement that is not part of global declaration part
always belongs to exactly one processing block. Statements within processing block are
processed sequentially. The arrangement of processing blocks in the implementation part
is not significant for program execution. The order in which processing blocks are
executed is controlled by calls (from other processing block) or by the ABAP runtime
environment. Each time a program is executed, at least one processing block is called by
the runtime environment as a point of entry, which, in turn, can call additional processing
blocks of same or other program. When first processing block of a program is called, the
entire program is loaded into the memory. When the last processing block is terminated,
control is returned to the calling program or runtime environment. Processing blocks
can’t be nested.

To keep the program readable, select a semantically relevant program structure and make
the structure visible using comment lines. The following types of processing blocks are
available.

• Procedures (methods, subroutines and function modules with their own local
data area)
• Dialog modules (processing blocks without local data)
• Event blocks (handle events of processes in the ABAP runtime environment)

32
START-OF-SELECTION statement introduces a processing block which plays the same
role in executable programs as the main method in Java program. That is, when program
is executed, the implementation of the block is automatically called.

The WRITE statement outputs a list and it is driven by the classic SAP Dynpro
technology which should not be used to applications with state-of-the-art user interface.
You should use Dynpro-based UIs only in test-programs if you want to output (or input)
some values in a quick and dirty way. You can compare the write-statement to the output
to the console in Java.

Comment lines are introduced by an asterisk * in the first position. To mark only the final
portion of a line as a comment, you can use the character “.

Object Oriented Version of “Hello World” Program

1. Select Create  Class Library  Class from the context menu of Z_MyPackage in
the Repository Browser. It will pop up the Create Class dialog.

2. Set the following fields in Create Class dialog.


Name: Z_CL_HW
Class Type: Usual ABAP Class
Brief Description: My hello world class
Instantiation: Public
Final: Check (Means that this class can’t be inherited)

33
3. Press Save button and you will be presented with Create Object Directory Entry
dialog, click save to continue.

4. Next dialog prompt for transport request. The transport request our package belongs
to is already in the relevant field. Again Confirm it.

5. In the Class Builder, select the Attributes tab to define attribute for a class. An
attribute is a data object declared within the class. Enter the following values in
respective columns.
Attribute: msg
Level: Instance Attribute
Visibility: Private
Typing: Type
Associated Type: string

34
6. Next to define the method, click on Methods tab. To define constructor push
Constructor (F5) button in class builder. To declare method, enter the following in
respective columns write after the CONSTRUCTOR.

Method: print_hello
Level: Instance
Visibility: Public
Description: This method will print hello world message

7. To implement the methods click the Source Code function .

8. Type the following statement in constructor. Make sure that the cconstructor is
selected in the list. To switch between the class builder and editor select previous
button and next button .

9. Next type the following statement in print_hello method.

10. This concludes the definition of class in class library so check and activate the class.
The dialog displays pending inactive objects. Click Continue to activate.

35
11. To consume this class, let’s create the program of type Subroutine pool.

Note: Subroutine pool is a type of ABAP program, where local classes are created and
their public methods are connected to transaction codes.

12. Right-click on the package Z_MyPackage and choose Create – Program.

13. Enter the name of the program we want to create Z_OO_HW. Deselect “With TOP
INCL“ (Top Include) because we do not need a top include and confirm.

14. Next dialog shows the properties of the new program. From the type list select the
type "Subroutine Pool" change or add no other properties. In particular, ensure that
the properties "Unicode checks active" and "Fixed point arithmetic" should always be
checked. Press Save button.

36
15. Create Object Directory Entry dialog appears, click save to continue.

16. Next dialog prompt for transport request. The transport request our package belongs
to is already in the relevant field. Again Confirm it.

17. This will open the ABAP Editor, enter the following listing.

37
18. Now if you activate and Execute (F8) the program. It won’t work, because subroutine
pool has no pre-defined starting point like START-OF-SELECTION for executable
programs. To solve this problem we have to define the transaction code.

Note: Transaction like the name “report“ for executable program, is historical in nature
and the reason for this context is explained by the fact that a classical ABAP application
program generally executed a business transaction on the database table. For us the
transaction means the execution of an ABAP program via “Transaction Code“. It is a
twenty-character name which is assigned to a screen or a method of an ABAP program
and is used for program execution.

19. Select Create  other(1)  Transaction from the context menu of our package in the
repository browser and fill the dialog window that appears.
Transaction Code: Z_HW
Short Text: Hello World
Start Object: Method of a class and Select Continue.

38
20. On next screen maintain OO transaction.
OO Transaction Model: Uncheck (to fill the input fields)
Class Name: z_cl_client
Method: main
Local in Program: Check
Local in Program: Z_OO_HW

21. Click Save on standard toolbar.

22. Create Object Directory Entry dialog appears, click save to continue.

39
23. Next dialog prompt for transport request. The transport request our package belongs
to is already in the relevant field. Again Confirm it.

24. To run, enter the \oZ_HW in the input field of the standard toolbar. /o runs the
program in new window, in contrast to /n.

Dissecting the OO Hello World Program

The declaration part contains the declaration of local class z_cl_client. The public section
show defines the public visibility of the static method main which is defined with
CLASS-METHOD statement.

The implementation part of local class must implement between CLASS......


IMPLEMENTATION and ENDCLASS. Between METHOD ... and ENDMETHOD we
provide the implementation for method.

The main method is a user for our global class. The REF TO means that obj is a
reference variable which is pointing to z_cl_client reference type or class. The CREATE
OBJECT creates the obj object. The selector -> is used for accessing an instance public
component.

40
ABAP Program Types
Unlike Java where programs are simply containers for classes, there are different ABAP
programs types that play different roles on the application server ABAP. The program
type defines the basic technical attributes of a program, that is, which processing blocks a
program may contain how the program is handled and executed by the ABAP runtime
environment, and whether it can work with its own screens (Also known as dynpros) are
the most general type of user dialog in SAP applications before NetWeaver. You do not
define them in ABAP programs, but instead in the Screen Painter.).

When you run an ABAP application program, you must call at least the first processing
block from outside the program, that is, from the runtime environment. This processing
block can then either call further processing blocks or return control to the runtime
environment. When you start an ABAP program, the runtime environment starts a
processor (dependent on the program type), which calls the first ABAP processing block.
The program can be started either by the user or by the system (for example, in
background processing), or through an external interface, for example, for Remote
Function Calls (RFC).

There are seven program types from which you can choose: executable program, module
pool, function group, class pool, interface pool, subroutine pool, and include program.

Class Pools / Global Class


Class pool is a container for exactly one global class and more than one data types and
local object types (local classes and interfaces). All the reusable code is programmed
here. A class pool is loaded into memory by using the global class, for example, a public
method of global class can be called from another ABAP program or it can be linked with
a transaction code. They are declared with the CLASS-POOL statement but as it is
created with Class Builder (SE24) of ABAP Workbench, which means it is generally not
displayed as a single continues source code.

Interface Pools / Global Interface


Interface pool is a container for exactly one global interface. The global interface can be
implemented in any global or local classes. They are introduced with the INTERFACE-
POOL statement. Interface pool is created in Class Builder (SE24) of the ABAP
Workbench.

Function Groups / Function Pools


Function group contains a procedures (Function Modules) processing block. Function
groups and their function modules are the procedural predecessors of global classes with
public methods. Function groups (like exe programs and module pools) can contain

41
dynpros as components, which is not possible in class pools. If you require working with
dynpros in ABAP Objects then function groups is the first choice. Function groups are
also required for RFCs. You can call function groups from methods but no more
functional coding should be created in function modules; instead you should branch from
there into methods. Function pools are introduced with the FUNCTION-POOL statement
and maintained with Function Builder (SE37) of ABAP Workbench.

Subroutine Pools
Subroutines pool contains a subroutine processing blocks that can be called by other
programs. The use of subroutine is obsolete in ABAP Objects. However, you can create
local classes in subroutine pools and connect their public methods to a transaction code.
A subroutine pool that contains a class with a main method that is connected to a
transaction code is very similar to Java program. Subroutine pools are created using the
ABAP Editor (SE38) of ABAP Workbench and are introduced with the PROGRAM
statement.

Executable Programs
Executable programs can contain all processing blocks supported in ABAP, with the
exception of function modules, and as many local classes as required. Executable
programs are often referred to as reports, and why running an executable program is often
called reporting. Analogously, the source code of an executable program starts with the
REPORT statement. Only executable programs can be called using their name. In ABAP
Objects, executable should only be used if direct execution using the name is important.
For technical point of view, executable programs are currently only required for
background processing. Today you should only handle the START-OF-SELECTION
event of the reporting (exe program) process and jump from the corresponding processing
block directly to a method of a local class. It is maintained directly in the ABAP Editor
(SE38) of ABAP Workbench.

Executable programs are only started with the SUBMIT statement. Although NetWeaver
AS ABAP offers several ways to call executable programs by entering their name on the
screen, the system still executes the SUBMIT statement in the background.

Module Pools
Module pool acts as a container for dialog modules called by the dynpros flow logic.
Module pools were originally designed for the dialog programming with dynpros. With
the exception of reporting event blocks and function modules, module pools can contain
all processing blocks supported in ABAP and as many local classes as required. Module
pools are no longer play a role in ABAP Objects. Instead, function groups should be used
as carriers of dynpros. Module pools are introduced with the PROGRAM statement. It is
maintained directly in the ABAP Editor (SE38) of ABAP Workbench.

42
Type Groups
Type groups only contain declaration part for global data types and constants which can
be made visible in any ABAP program. Type groups are predecessor technology for
general type definitions in the ABAP Dictionary and in global classes or interfaces. No
more type groups should be created in ABAP Objects. Instead, types and constants can be
published by global classes and interfaces. Type groups are introduced with the TYPE-
POOLS statement. It is maintained with ABAP Dictionary (SE11) tool of the ABAP
Workbench.

Include Programs
Include programs have no introductory program statement and, unlike all other program
types, they do not represent independent compilation units with their own memory space.
Include programs provide a library function for ABAP source code and can be embedded
at any location in other ABAP programs using the INCLUDE statement. During syntax
check the INCLUDE statement is replaced by the source code of the include programs.
Include programs have no technical relationship to processing blocks. However, it is
preferable to separate logical program units, such as the declaration part for global data,
and similar or individual processing blocks into independent include programs. They are
automatically generated by ABAP Workbench when you create programs such as class
pools or function pools. You can create your own include programs directly with the
ABAP Editor (SE38) tool of ABAP Workbench.

Include programs make large program much easier to handle, as it can be transported
individually, which allows, individual methods or function modules to be processed
independently of their class pool or their function group.

The “TOP include” is designed for the global declaration part of an ABAP program. The
naming convention is that the name of top includes ends with “TOP”. When you organize
program using include program, all statements of global declaration part should be
included by the top include. It can be created automatically when you create an ABAP
program in the ABAP Workbench by simply selecting the corresponding checkbox.

Include programs should never be sued for multiple usage of source code in several
compilation units. Instead, you can use global classes or interfaces. The reason for this
that the inclusion of an include program in several programs dramatically restricts both
their maintainability. Further more, an include program that is included in several
programs is loaded several times into the program memory of the application server, if
the programs are used in parallel. We recommend the declaration part of a local class or
processing block (method). The names of include programs should correspond to those
that are proposed by the ABAP Workbench.

The following matrix shows all ABAP program types and their supported features.

43
Recommended Program Types with ABAP Objects
• Use class and interface pools for reusable code in global classes and interfaces.
• Subroutine pools can serve as Java-like programs in which you can call exactly
one main method from outside.
• The same applies for exe programs as for subroutine, though you can call them
using SUBMIT statement, which is technically suitable for background processes.
• Use function groups only where technically necessary, that is, as containers for
dynpros and for RFC-enabled function modules.
• New module pools or type groups should no longer be created for programming
with ABAP Objects.

44
ABAP Program Processing Blocks
An ABAP program is embedded in a runtime environment provided by Application
Server ABAP. The runtime contains processors that execute the ABAP programs. The
execution of ABAP program is synonymous with a process in ABAP runtime
environment, which controls the program by calling the processing blocks. However
most of the concept of processors are primarily connected to procedural/event oriented
ABAP programming and has lost significance for modern ABAP Objects. The following
types of processing blocks are available.

• Procedures
• Dialog Modules
• Event Blocks

Procedures
Procedure processing blocks have a local data area and can have a parameter interface.
Procedure can be in the form of Method, Function Modules or Subroutines.

Methods

Method is a component of a class. OO ABAP program is built from methods that are
organized in classes. Method processing blocks can only be defined in class pools
program type. METHOD statement and concluded with the ENDMETHOD statement. You
call methods from ABAP programs using the CALL METHOD statement.

Function Modules

These are predecessors of methods for external procedure calls in the procedural
programming model. It is also called external procedure. Function modules can only be
created in function groups or function pools program type. Since many functions
(dynpros and RFC) of an ABAP are still offered in function modules, they can continue
to be called from methods. Function modules are introduced with the FUNCTION
statement and concluded with the ENDFUNCTION statement. You call function modules
from ABAP programs using the CALL FUNCTION statement.

Subroutines

These are predecessors of methods for internal procedure calls in the procedural
programming model. It is also called internal procedures. Subroutines are replaced
entirely by methods and should no longer be used. Instead you can create local classes for
internal modularization in all program types that can contain operational code.

45
Subroutines are introduced with the FORM statement and concluded with the ENDFORM
statement. You call subroutines from ABAP programs using the PERFORM statement.

Dialog Modules
Dialog Modules are processing blocks without a local data area and without a parameter
interface. They can only work with global data from the declaration part of their ABAP
program, which prevents data encapsulation. They can be used in ABAP programs that
support their own dynpros (executable programs, function groups, module pools). Dialog
modules processing blocks should contain little or no operational code other than method
calls. Dialog modules are rarely needed nowadays. Dialog modules are introduced with
the MODULE statement and concluded with the ENDMODULE statement. Dialog modules
called from the screen flow logic (screen command MODULE).

Event Modules
Even Modules are processing blocks without a local data area and without a parameter
interface. They can only work with global data from the declaration part of their ABAP
program, which prevents data encapsulation. Classical ABAP programs and executable
programs particularly are event-oriented. Event blocks are called through events which
are triggered by user actions on selection screens and lists or by the ABAP runtime
environment. ABAP Objects has an explicit event concept where events are triggered by
a statement in methods and are handled by special methods (event handlers). The events
blocks can be divided into:

Program Constructor Event Block

Directly after an executable program, a module pool, a function group or a subroutine


pool has been loaded, a special processing block can be executed exactly once. This
block can be used for global data initialization. Therefore it resembles class constructor.
This processing block is defined as an event block using the event keyword LOAD-OF-
PROGRAM.

Selection Screen Event Block

It is triggered by the screen selection processor of ABAP runtime environment during


selection screen processing. Selection screens are special dynpros.

List Event Block

It is triggered by the list processor of the ABAP runtime environment during classical list
processing. In ABAP Objects the creation and processing of classical lists is obsolete in
most cases.

46
Reporting Event Block

It is triggered by the reporting processor of the ABAP runtime environment if an


executable program is executed. In ABAP Objects you should only implement the
START-OF-SELECTION.

47
Elements of ABAP Language
Statements
Each ABAP program is composed of one or more statements. Each statement contains
one or more words separated by at least one space. The first word of a statement is the
keyword. A statement can include one or more additions, and always ends with a period.

The first keyword of statement determines the category of the statements. The different
statement categories are as follows:

Declarative Statements

These statements define data types or declare data objects which are used by the other
statements in a program or routine. The collected declarative statements in a program or
subroutine make up its declaration part. Examples of declarative keywords: TYPES,
DATA, TABLES.

Modularization Statements

These statements define the processing blocks in an ABAP program. Examples of


modularization keywords: START-OF-SELECTION, MODULE ... ENDMODULE.

Control Statements

You use these statements to control the flow of an ABAP program within a processing
block according to certain conditions. Examples of control keywords: IF, WHILE,
CASE.

Call Statements

You use these statements to call processing blocks that you have already defined using
modularization statements. The blocks you call can either be in the same ABAP program
or in a different program. Examples of call keywords: PERFORM, CALL, SET
USER-COMMAND, SUBMIT, LEAVE TO.

48
Operational Statements

These keywords process the data that you have defined using declarative statements.
Examples of operational keywords: WRITE, MOVE, ADD.

Database Statements

These statements use the database interface to access the tables in the central database
system. There are two kinds of database statement in ABAP: Open SQL and Native SQL.

Open SQL: Open SQL is a subset of the standard SQL92 language. It contains only Data
Manipulation Language (DML) statements, such as SELECT, INSERT, and DELETE. It
does not contain any Data Definition Language (DDL) statements (such as CREATE
TABLE or CREATE INDEX). Functions of this type are contained in the ABAP
Dictionary. ABAP programs that use only Open SQL statements to access the database
are fully portable. The database interface converts the OPEN SQL commands into
commands of the relevant database.

Native SQL: Native SQL statements are passed directly from the database interface to
the database without first being converted. It allows you to take advantage of all of your
database’s characteristics in your programs. In particular, it allows you to use DDL
operations. The ABAP Dictionary uses Native SQL for tasks such as creating database
tables. In ordinary ABAP programs, it is not worth using DDL statements, since you
cannot then take advantage of the central administration functions of the ABAP
Dictionary. ABAP programs that use Native SQL statements are database-specific.

Chained Statements
The ABAP programming language allows you to concatenate consecutive statements
with an identical first part into a chain statement.

To concatenate a sequence of separate statements, write the identical part only once and
place a colon (:) after it. After the colon, write the remaining parts of the individual
statements, separating them with commas. Ensure that you place a period (.) after the last
part to inform the system where the chain ends.

Statement sequence:

WRITE ‘Hello’.
WRITE ‘to the’.
WRITE ‘world of ABAP’.

Chain statement:

WRITE: ‘Hello’,
‘to the’,

49
‘world of ABAP’.

In a chain statement, the first part (before the colon) is not limited to the keyword of the
statements.

Statement sequence:

SUM = SUM + 1.
SUM = SUM + 2.
SUM = SUM + 3.
SUM = SUM + 4.

Chain statement:

SUM = SUM + : 1, 2, 3, 4.

50
Data Objects and Data Types
Data Objects
Data object is a named memory that is structured according to a particular data type. Data
objects are instances of data types. Each ABAP data object has a set of attributes (field
length, number of decimal places) which it acquires from its data type. Data objects
reside in repository.

Data objects can be created by using declarative statements (DATA statement) or


CREATE DATA statement. Data objects that have been created using declarative
statements are assigned name and can be accessed through this name. Data objects
created using CREATE DATA are not assigned a name (anonymous data objects) and can
be addressed only via reference variables, similar to class instances.

DATA data_obj TYPE data_type [LENGTH len] [DECIMALS dec]


VALUE val] [READ-ONLY].

The statement defines a data_obj data object of type data_type. LENGTH must be
used for incomplete types (p,c,n and x) discussed later. The DECIMALS is used to define
the number of decimal places for packed number type (p). The VALUE addition defines
the initial value for data object data_obj. READ-ONLY addition can be used to declare
an attribute in the public visibility section of a class (discussed in class section) in such
away that its contents can not be changed from out side the class.

CREATE DATA data_obj_ref TYPE data_type [LENGTH len]


[DECIMALS dec].

Data objects have three levels of visibility (aka Context of Data Object): global, local,
and class. The visibility of a data object indicates from where in the program the data
object is accessible.

Global Data Objects: can be accessed from anywhere within the program. They are
declared in the declaration part of a program. The life cycle of global data object is bound
to the life cycle of its program in the internal session. In ABAP Objects, avoid using
program global data, instead use global classes.

Local Data Objects: are accessible only from inside the methods or other procedures
(function modules, subroutines) in which they are defined. The life cycle of local data
object spans over the body of method or procedure.

Class Level Data Objects: Data declarations in the declaration part of classes either
create instance attributes or static attributes. Instance attributes can b addressed in all
instance methods, while static attributes can be addressed in all methods via their names.

51
The life cycle of an instance attribute depends on the lifecycle of an object, while the life
cycle of a static attribute depends on the life cycle of an internal session.

Data objects can be of the form: Literals, Variables, Constants or Text Symbol.

Literals

Literals are not created by declarative statements. Instead, they exist in the program
source code. Like all data objects, they have attributes (field length, number of decimal
places, data type), but no name. They are therefore referred to as unnamed data objects.
Literals can be numeric or character. For example; 12356, or “Hello World”.

Variables

Variables are named data an object that you can declare statically (compile time) using
declarative statements or dynamically while a program is running. They allow you to
store changeable data under a particular name within the memory area of a program. You
declare variables using the DATA, CLASS-DATA, STATICS, PARAMETERS,
SELECT-OPTIONS, and RANGES statements.

Constants

Constants are data objects whose contents cannot be changed. You declare constants
using the CONSTANTS statement. You cannot define constants for XSTRINGS,
references, internal tables, or structures containing internal tables.

CONSTANT data_obj TYPE data_type VALUE val | {IS INITIAL}.

IS INITIAL is use to set a constant data_obj to its type specific initial value.

Text Symbols

Text symbols are pointers to texts in the text pool of the ABAP program. The text pool
contains the text elements of the program, several text pools can be defined in different
languages for a program. When the program starts, the corresponding data objects are
generated from the texts stored in the text pool. They can be addressed using the name of
the text symbol. Text Symbols are maintained with Text Element Maintenance (SE32) of
the ABAP Workbench. Text Symbols are linked to the translation, i.e. you can use text
symbols in places where you want to display texts from the program on the user interface,
without to bother about the logon language of specific user.

52
Data Types
Data types specify the attributes of data objects. Data type determines how the data is
stored in the memory, and tells the ABAP statement how to handle it. Data types do not
occupy memory. The TYPE keyword defines the data type for data object as:

DATA txt TYPE c LENGTH 12 VALUE ‘Hello World’.

Here txt data object is an instance of data type c with initial value “Hello World”. In
ABAP we have the following data types.

Elementary Data Types

These are data types of fixed or variable length that are not made up of other types. There
are eight fixed length and two variable length elementary data types. The difference
between variable length data types and fixed length data types is that the length and the
memory space required by data objects of variable length data types can change
dynamically during runtime.

You can also define your own elementary data types in ABAP using the TYPES
statement. You base these on the predefined data types. This determines all of the
technical attributes of the new data type.

There are total 10 built-in elementary data types:

• Fixed Length Elementary Data Types

The “Length” column indicates the minimum and maximum number of bytes or
characters that a data object can occupy. The interval is specified in length
column for p, c, n and x data types means that these data types are incomplete or
generic and it is required to use the LENGTH addition to specify their length,
otherwise you cannot use them to declare data types and data objects. The other
types i, f, d, and t are not generic and complete, you don’t need to specify
LENGTH when declare a data object or data type. In fact, specifying length in this
is forbidden.

Data objects that are declared using one of these eight data types are referred to as
static data objects because the utilized memory space is statically (during
declaration).

53
Standard
Data Type Length Initial Value Meaning
Length
Numeric Data Types
i 4 bytes 0 Integer
f 8 bytes 0 Floating point
p 1-16 bytes 8bytes 0 Packed number
Character Data Types
1 - 65535 Text Field
c 1 character ‘….’
characters (Alpha numeric)
Numeric Text
1 - 65535
n 1 character '0 … 0' Field (Numeric
characters
characters)
Date Field
d 8 characters ‘00000000' (Format:
YYYYMMDD)
Time Field
t 6 characters '000000' (Format:
HHMMSS))
Hexadecimal (Byte) Data Type
Hexadecimal
x 1-65535 bytes 1 byte x'00 …00'
field

• Variable Length Elementary Data Types

Standard
Data Type Length Initial Value Meaning
Length
Character Data Types
string Character Strings
xstring Byte Strings

Complex Data Types

Complex data types are made up of other data types. Complex Data Types allow you to
manage and work with semantically related datasets under a common name. There is nor
built-in complex data types. A complex data type must be constructed from existing
types. Complex data types can be structured types or table types.

54
Reference Data Types

Reference types describe data objects (reference variables) that contain references to
other objects. There are types of data references (references to data objects) and object
references (references to instances of classes).

55
Defining Data Types
There are two ways to define data types in ABAP:

• Bound Data Type


• Independent Data Type

Bound Data Type

The data statement DATA creates a bound data type. That is a type defined only for that
particular data object and can’t be used for other data objects.

DATA msg TYPE c LENGTH 20 VALUE ‘Hello’.

The above statement declares msg data object of type c with length of 20 characters.
Now these properties i.e. type and length is just associated or bound with data object
msg. If we try the following declarative statement.

DATA txt TYPE msg VALUE ‘Welcome’.

You will get an error saying that type msg is unknown. This shows that the properties
like type and length is bound to msg and you can’t use the TYPE addition to msg to
define data objects of type msg.

The LIKE keyword is used to solve the above problem. For example the following line is
executed without any errors.

DATA txt LIKE msg VALUE ‘Welcome’.

The above line says that txt is a data object having same properties as that of msg.
LIKE refers to predefined data objects. But the problem with this method is we are
creating data objects even for the purpose of defining data types i.e. LIKE similar to
TYPE also allocates memory space. As a result, this would consume a lot of memory.
For this reason ABAP provides an independent data types.

Independent Data Types

Independent data types act as a template for data objects, similar to classes that can be
used for template for objects. The TYPES keyword is used to define an independent data
types. The TYPES keyword creates data type and does not allocate memory space. The
syntax of TYPES is almost identical to the DATA statement but without data object
specific additions like length and value etc.

56
The TYPES statement for an independent character-like data type text of length 20 would
be as follows:

TYPES text TYPE c LENGTH 20.

To declare data objects of type text:

DATA txt1 TYPE text VALUE ‘Welcome’.


DATA txt2 TYPE text VALUE ‘to ABAP’.

This means, that txt1 and txt2 are of type text which in turn of type c and having length of
20.

With so many different ways to declare data types, the question arises as to when you
should use which option?

• It is good programming style to create a self-defined data type only as an


independent type.
• Use LIKE addition whenever your declaration is directly liked to a data object.
Examples of this include auxiliary variables in procedures that must have the
same type as interface parameters or their components. This keeps your program
valid even if the data type of the data objects changes.
• In all other cases, you should use the TYPE addition to directly reference
appropriate independent data types.

57
Elementary Data Types Usage
Numeric Data Types

• Data Type i: i is a complete type, used for integers, having size of 4-bytes. Often
used for index or count variables. The default value is 0.

DATA count TYPE i VALUE 0.

• Data Type f: f is a data type for binary floating point numbers. f is a complete
type. It is having 8-bytes of size. It is consists of three components: the +/- sign, a
16-digit mantissa and the exponent. Mantissa contains the digits of the number,
while the exponent specifies the position of the decimal point. The default value is
0.

DATA result TYPE f.

• Data Type p: p is incomplete type. It is packed numbers in the Binary Coded


Decimals (BCD) format with fixed number of decimal places. The number of
decimal places is defined during declaration of data type or data object using the
DECIMALS addition after TYPE. The default value is 0. The type p is useful for
monetary amounts, dimensions or weights etc.

DATA number TYPE p DECIMALS 2 VALUE 23.

With SAP NetWeaver 2007 new data type decfloat16 and decfloat34 are
introduced to replace the f and p data types.

• Data Type decfloat16: decfloat16 is complete type. It is decimal floating point


number with 16 decimal places. It is having 8-bytes of size. The default value is 0.

DATA no TYPE decfloat16 VALUE 12.

• Data Type decfloat34: decfloat34 is complete type. It is decimal floating point


numbers of this type are represented internally with 34 decimal places. It is
having 16-bytes of size. The default value is 0.

DATA no TYPE decfloat34 VALUE 23.

Character Data Types

• Data Type c: c is a data type that can be used for any character string of fixed
length. c is incomplete data type for this purpose you must specify the length
property for this data type.

58
DATA txt _line TYPE c LENGTH 72.
txt_line = ‘ABAP programming is fun!”.

• Data Type n: Type n is a special case of type c for numeric characters, but not a
numeric data type. n is also incomplete data type. Data objects of this type can
only contain numbers, but these numbers can not be directly used to carry out
calculations. Typical use areas can be ZIP codes, Phone Numbers, P.O Box
numbers etc.

DATA postal_code TYPE n LENGTH 5.


postal_code = ‘25000’.
• Data Type d: d is data type for date information in the format, YYYYMMDD. d is a
complete type. If data object of type d is used in the position of operands where a
numerical value is expected, the date is regarded as a number that corresponds to
the number of days that have been passed since 00010101. Other operations
utilize the character nature.

DATA today TYPE d.


today = sy-datum.
today = today + 2.

The sy-datum system field provides the system date, after the calculation, it
assign the date of day after tomorrow.

• Data Type t: t is a data type for time information in the format, HHMMSS. It is
complete data type. . If data object of type d is used in the position of operands
where a numerical value is expected, the time is regarded as a number that
corresponds to the number of seconds that have been passed since midnight
000000. Other operations utilize the character nature.

DATA now TYPE t.


now = sy-uzeit.
now = now + 3600.

The sy-uzeit system field provides the current time, and then one hour is
added to the now data object.

• Data Type x: x is a data type used for storing byte strings of fixed length. It is
incomplete data type. Type x data objects can generally be used for byte-like
content where the fixed length is important.

DATA hex TYPE x LENGTH 3.


hex = ‘F3456AB’.

59
• Data Type string: Type string is a data type that can be used for any characters
strings of variable length. The LENGTH addition is not allowed with string data
type; however you can use the VALUE addition to initialize a string data object.

DATA txt_str TYPE string.

• Data Type xstring: xstring is a data type that can be used for any byte string of
variable length. The LENGTH and VALUE and addition is not allowed with xstring
data type.

DATA txt_xstr TYPE xstring.

60
Complex Data Types
Complex data types can be structured types or table types.

Structured Data Type

Structured data type is consists of a sequence of other data types. The data object of a
structured data type is called structure. The units that make up a structured type are called
structure components (fields). The components of the structure can be elementary data
types, a structure, an internal table or a reference data type. Structures are used especially
to define the data at the interface of module pools and screens and to define the types of
function module parameters.

There are Flat, nested and deep structures. A flat structure only references elementary
types. A nested structure references at least one further structure, but not a table type. A
deep structure references at least one table type.

The BEGIN OF and END OF statements define the beginning and end of a structure as a
bound or independent type:

DATA: BEGIN OF structure_name,

struct_comp1 TYPE|LIKE …,
struct_comp2 TYPE|LIKE …,
………
………
struct_compn TYPE|LIKE …

END OF structure_name.

TYPES: BEGIN OF structure_name,

struct_comp1 TYPE …,
struct_comp2 TYPE …,
………
………
struct_compn TYPE…

END OF structure_name.

The addition of BEGIN OF and END OF statements define the beginning and end of a
structure called structure_name. The colon and the commas indicate that we are
dealing with several DATA and TYPES statements. All the statements that lie in-between

61
declare the components of the structure. A component that is structured itself is referred
to as a substructure. A structure that contains substructures is called nested structure.

The component of a structure can be accessed with structure component (-). For nested
structures, you must concatenate the structure names to access internal components.

62
The program produces the following out put.

For the street, we created a separate structured type street_struct with components
name and no. For the address, we declare a structure address_struct as a data
object (everything we discussed for DATA also holds true for CLASS-DATA, for
declaration of static attributes.) and we declare the street component with type
street_struct. The substructure city_struct consists of two components
zipcode and name.

You can integrate the components of a structure into another structure using the
INCLUDE statement as:

DATA BEGIN OF struct_1,


……
INCLUDE STRUCTURE struct_2 AS name

63
[RENAMING WITH SUFFIX suffix].
……
DATA END OF struct_1.

TYPES BEGIN OF struct_1,


……
INCLUDE TYPE struct_2 AS name
[RENAMING WITH SUFFIX suffix].
……
TYPES END OF struct_1.

The INCLUDE statement is not an addition to the TYPES or DATA statements. Instead, it
interrupts the chained statement that must be restarted afterwards.

The components of struct_2 will be transferred as components into the struct_1


structure. They can either be addressed commonly under the name name, or individually
by their component names. The RENAMING addition can be used to avoid naming
conflicts.

64
The program produces the following out put.

All the components are allocated at the same level. Naming conflicts between the name
components are avoided by the use of different endings. This type of structure definition
avoids complex nested structures with long name chains.

Table Types

Table types represent the second complex data type. The data objects of table types are
internal tables. Internal tables are dynamic data objects like strings; internal tables are
internally managed by references. An internal table consists of a dynamic sequence of
lines of the same data type (it can be think of an arrays in Java or C#.Net). The table type

65
describes the line type, the table category and a table key. The following syntax can be
used to declare the internal tables.

DATA tab_name TYPE|LIKE STANDARD|SORTED|HASHED TABLE


OF data_type|data_object
WITH [NON-]UNIQUE KEY col1…coln.

TYPES tab_name TYPE STANDARD|SORTED|HASHED TABLE


OF data_type
WITH [NON-]UNIQUE KEY col1…coln.

The keywords STANDARD, SORTED and HASHED define the table category.

STANDARD Table: is managed internally by a table index. Access is possible via table
index or table key. With a key access, the response time is directly dependent on the
number of table entries. The key of a standard table is always non-unique. This table
category is suited best whenever the individual entries can be accessed using the index.

SORTED Table: is managed internally by means of a table index, too. They are always
sorted by the table key and can be accessed via the table index or the table key. With a
key access, the response time is logarithmically dependent on the number of table entries,
because the table is accessed via a binary search. The key of sorted tables can be unique
or non-unique. This table category is suited whenever the table must already be sorted
when it is filled.

HASHED Table: is managed internally by a hash algorithm. Hashed tables can be


accessed only via the table key. The response time is constant, independent of the number
of table entries. The key of hashed tables is always unique. This table category is suited
whenever the key accesses represent the central operation on the table entries.

The data_type and data_object represent the line type. The internal table can
contain any number of lines of the specified line type. Thus, line type is fixed during
declaration, but not the number of lines. You can use any line type, elementary types,
reference types, structures and even other internal tables.

The table key is required for the identification of table rows. An internal table has a
unique or non-unique table key that can be defined by listing its components.

Example below demonstrates the usage of internal table.

66
After executing the loop will display five message boxes as:

67
Example above declares a standard table array whose line type is elementary data type
i and whose key consists of the DEFAULT KEY. DEFAULT KEY is build from all
columns of the internal table that have a character-type type (c, d, t, n, x, string,
xstring). The APPEND statement appends a new line to the end of the indexed internal
table. The sy-index is a system field (System fields are filled according to the context
by system runtime) gets the particular record number. It acts like Loop Iteration Counter.

Reference Data Types


Reference types can contain a reference to other data objects or to instances of classes.
Those data objects are referred to as reference variables. Depending on the type of object
that is referenced, we speak of data reference variables or object reference variables that
can either contain data references or object references. The following syntax can be used
to declare the reference data types.

DATA ref_variable TYPE |LIKE REF TO


data_type|data_object.

68
TYPES ref_variable TYPE REF TO data_type.

DATA obj_ref TYPE REF TO class|interface.


TYPES obj_ref TYPE REF TO class|interface.

The first two statements create the reference variable for data reference. Next two
statements create an object reference for class or interface. All of the data objects that you
define in the declaration part of a program using statements such as DATA are created
statically, and already exist when you start the program. To create a data object
dynamically during a program, you need a reference variable and the following
statement:

CREATE DATA ref_variable TYPE |LIKE


data_type|data_object.

CREATE DATA ref_variable TYPE data_type.

The statements create a reference variable in the internal session of the current ABAP
program. After the statement, the data reference in the data reference variable points to
the object.

The object component selector (->) can be used to access the components of the
reference variable. The dereferencing operator (->*) can be used to access the entire data
objects that is referenced.

The following statements allow you to place a data reference to an existing data object in
a reference variable:

GET REFERENCE OF data_object INTO ref_variable.

Example below demonstrates the usage of reference variable and object references.

69
The program produces the following results.

The declaration section introduces the obj_ref is an object reference to cls class,
while data_ref1 and data_ref2 are reference variables to obj_ref and i
respectively.

CREATE OBJECT statement allocates the reference obj_ref which enable us to


access its attribute var. The GET REFERENCE OF statement gets the reference of
obj_ref and places it into the data_ref1 reference variable.

70
CREATE DATA statement creates a data object data_ref2 dynamically. On next line
through dereferencing operator (->*) we access the var attribute of obj_ref
(data_ref1 is pointing to obj_ref) and assign to data_ref2. After execution it is
clear that both obj_ref and data_ref2 are pointing to same memory location.

Generic Data Types


The generic data types allow the dynamic programming. By generic we mean that the
data type is determined during runtime. Table below lists the predefined generic types in
the first column, while the second column describes the types they comprise. You can
assign a data object with a type from the second column to a formal parameter r field
symbol (Field symbols are placeholders or symbolic names for other data objects. Field
symbols are similar to dereferenced pointers in C) that is typed with a generic type from
the first column.

Generic Type Types Comprised


any, data All data types
c, d, n, t, string, and flat structures containing
clike
character like components
csequence c and string (text like types)
xsequence x and xstring (byte like types)
any table All table types
sorted table Sorted tables
hashed table Hashed tables
index table Standard and Sorted tables
standard table, table Standard tables
numeric i (b,s), p , f (numeric types)
Corresponding built-in types with generic lengths
c, n, p, x
and decimal places
c, d, f, i (b,s), n, p, t, string, x, xstring, and flat
simple
structures containing character like components

If table type is defined using the TYPES statement or if it is defined in the ABAP
Dictionary without specifying a key, this table type is also generic type.

Flat and Deep Data Types


All data types in which the content of their data objects represents actual working data
are referred to as flat data types. Thus all elementary data types of fixed length are flat
data types.

All data types in which content of their data objects are references that point to working
data in different locations of the memory are referred to as deep data types. Thus
reference types and dynamic data objects (strings and internal tables) are deep data types.

71
In assignment between deep data objects; for assignments between reference variables,
reference semantics applies i.e. only the references are copied, but not the referenced
objects. For assignment between dynamic data objects (strings and internal tables), value
semantics applies i.e. the referenced object is copied and a new reference is created.

The memory requirement for deep data objects is combination of a constant requirement
for the reference (8 bytes) and a dynamic requirement for actual objects.

72
ABAP Dictionary
ABAP Dictionary is a central global storage for data definitions (metadata) of user
defined types (data elements i.e. elementary types, structures, table), indexes, views and
domains that can be accessed by all repository objects, provided this is permitted by the
package check. The ABAP Dictionary describes the logical structure of the table and
views used in application development and shows how they are mapped to the underlying
relational database in tables or views. The ABAP Dictionary also provides a number of
services that support program development. For example, setting and releasing locks,
defining an input help (F4 help) and attaching a field help (F1 help) to a screen field are
supported.

Data types of the ABAP Dictionary play the same role as the global types that are
declared using the TYPES statement in classes and interfaces. Data types of the ABAP
Dictionary enable a type-specific transfer of values between dynpros and ABAP
programs.

When defining tables, first a structured type is created in the ABAP Dictionary, based on
this structured type a physical database table is generated in the database. To use data
from database tables, you must declare data objects in an ABAP program.

ABAP Dictionary contains many more built-in types than the ABAP programming
language, and these types also have different names. The difference between the data
types is based on the fact that the built-in data types of the ABAP Dictionary must be
compatible with the external data types of the database tables supported by the AS
ABAP. If an ABAP program, you reference a data type from the ABAP Dictionary; the
elementary components of that data type are converted into the built-in data types of the
ABAP programming language. Table below provides an overview of all built-in data
types of the ABAP Dictionary and their counterparts in ABAP programs.

Dictionary ABAP
Description
Type Type
Posting Period: The length is set to 6 places for this data
type. The format is YYYYMM. In input and output, a
ACCP n
point is inserted between the year and month, so the
template of this data type has the form ‘____.__’.
Character string: Fields of type CHAR may have a
maximum length of only 255 in tables. If longer character
CHAR fields are to be used in tables, you must choose data type c
LCHR. There are no restrictions on the length of such
fields in structures.
CLNT Client: Client fields always have three places. c
Currency key: Fields of this type are referenced by fields
CUKY of type CURR. The length is set to 5 places for this data c
type.

73
Currency field: Equivalent to an amount field DEC. A
field of this type must refer to a field of type CUKY
CURR p
(reference field). The maximum length for this data type
is 31 places.
Date: The length is set to 8 places for this data type. The
DATS d
output template can be defined with the user profile.
Counter or amount field: with decimal point, sign, and
DEC commas separating thousands. A DEC field has a p
maximum length of 31 places.
Floating point number: The length (including decimal
FLTP f
places) is set to 16 places for this data type.
1-byte integer: between 0 and 255. The length is set to 3
INT1 b
places for this data type.
2-byte integer: between -32767 and 32767. Fields of this
type should only be used for length fields. With INSERT
INT2 or UPDATE on the long field, the database interface s
enters the length which was actually used in the length
field. The length is set to 5 places for this data type.
4-byte integer: between -2147483647 bis 2147483647.
INT4 i
The length is set to 10 places for this data type.
Language key: This data type always has length 1. The
LANG language key is displayed at the user interface with 2 c
places, but is only stored with 1 place in the database.
Character string of any length: but has to be declared with
a minimum of 256 characters. If there is an INSERT or
UPDATE in ABAP programs, this length field must be
LCHAR filled with the length actually required. If the length field c
is not filled correctly, this may lead to a data loss in the
LCHR field! Fields of this type cannot be used in the
WHERE condition of a SELECT statement.
Long byte string: of any length, but has to be declared
with a minimum length of 256. If there is an INSERT or
UPDATE in ABAP programs, this length field must be
LRAW filled with the length actually required. If the length field x
is not filled correctly, this may lead to a data loss in the
LRAW field! Fields of this type cannot be used in the
WHERE condition of a SELECT statement.
Numeric text: Long character field in which only
NUMC numbers can be entered. The length of this field is limited n
to a maximum of 255 places.
Precession: Accuracy of a QUAN field. The length is set
PREC s
to 2 places for this data type.
Quantity. Equivalent to an amount field DEC. A field of
this type must always refer to units field with UNIT
QUAN p
format (reference field). The maximum length for this
data type is 31 places.

74
Byte string: Fields of type RAW may have only a
RAW maximum length of 255 in tables. If longer raw fields are x
required in tables, you should select data type LRAW.
Variable byte string: In the Dictionary a length can be
specified for this type (at least 256 characters). As default
RAWSTRING xstring
for the output length 132 characters are proposed. You
cannot attach search helps to components of this type.
Variable character string: In the Dictionary a length can
be specified for this type (at least 256 characters). As
STRING default for the output length 132 characters are proposed. string
You cannot attach search helps to components of this
type.
Short character string: In the Dictionary the number of
characters can be specified for this type (1-255). String
SSTRING fields of this type can be used in indexes and in the string
WHERE condition of a SELECT statement. You cannot
use them in table keys.
Time: The length is set to 6 places for this data type. The
TIMS format is hhmmss. The template for input and output has t
the form ‘__.__.__’.
Unit: Fields of this type are referenced by fields of type
UNIT c
QUAN. The length of this data type is set to 2 or 3 places.

You can not directly reference the built-in data types of the ABAP Dictionary in an
ABAP program. Instead you must reference types of the ABAP Dictionary that are
created on the basis of those data types. Note the type b and s can’t be directly specified
in ABAP; however they are internally assigned when dictionary types INT1 and INT2
are referenced. Type b and s behave like type i, but value ranges are more limited i.e. 0
to 255.

75
The ABAP Dictionary Tool can be used to define ABAP Dictionary types. It can be
called either by selecting Create  Dictionary Object  ……. from the context menu of
package in Object Navigator or by entering transaction code SE11.

Creating Elementary Data Type

An elementary type is defined by the built-in data type, length and possibly the number of
decimal places. These type attributes can either be defined directly in the data element or
copied from a domain.

1. To define elementary data type; select Create  Dictionary Object  Data


Element from the context menu of package.

76
2. Enter the name for data element.

3. This will open the Dictionary: Maintain Data Element window; select Predefined
Type on Data Type tab. Select NUMC from data type and enter length of 8.

4. On the Field Label tab you can maintain text information for the data element.
The field labels are used to display a Dynpro screen field. Keywords of different
lengths (Short, Medium and Long) for identifying screen fields. Heading is used
as a column header when you output the contents of fields as a list in the Data
Browser. The Further Characteristics tab maintains help (F1) and input help (F4).
Click Save button.

5. The Create Object Directory Entry dialog will pop up save it. Next confirm the
Prompt for transportable Workbench request dialog.
6. Confirm the Maintain field label.

77
7. Now you can see that new entry with the name Dictionary Objects is added to the
tree under the Z_MYPACKAGE.

8. To activate choose the Activate function from toolbar.


9. The following code shows the usage of our newly created ABAP Dictionary type
Z_DIC_TYPE.

78
10. On executing the above code, it produces the following output.

Creating Domains

A domain defines a value range. A domain is assigned to a data element. All table fields
or structure components that use this data element then have the value range defined by
the domain. The relationship between the field or component and the domain is thus
defined by the data element of the field or component.

Fields or components that refer to the same domain (with the assigned data elements) are
also changed when the domain is changed. This ensures that the value ranges of these
fields or components are consistent.

1. Enter SE11 to open the ABAP Dictionary: Initial Screen.


2. Select object type Domain, enter the name of Domain Z_DOM and choose create
button.

79
3. The maintenance screen for domains appears. Enter an explanatory short text in
the field Short text.
4. On the Data type tab page, choose the data type, number of places (valid positions
without editing characters such as comma or period) and number of decimal
places (only needed for data types DEC, FLTP, QUAN and CURR). Note that some
data types have a fixed length. For example, the data type CLNT (client) always
has 3 places. If you enter an invalid number of places for such a data type, the
system corrects this automatically after issuing a warning.

5. If only certain input values are valid for the domain, you can enter them in the
Value range tab page as fixed values. If fixed values are defined for a domain,
these are used in the input check in screen templates. You can define fixed value
intervals either by entering upper and lower limits or by specifying single values.
It is only possible to define fixed values for domains of data types CHAR, NUMC,
DEC, INT1, INT2 and INT4.

80
6. Save the domain. Confirm the Create Object Directory Entry and Transportable
Workbench request.
7. The Domain entry is now visible in Object Navigator tree. Activate it.

8. Next to create the elementary type based to our newly created domain Z_DOM.
Select Data Type, enter the name of data type Z_DOMAIN_TYPE and choose
create button.

81
9. Select Data element on next dialog and confirm.

10. On Dictionary: Maintain Data Element window, enter the short text and domain
Z_DOM and save it.

82
11. Confirm the Create Object Directory Entry, Maintain field label and
Transportable Workbench request.
12. The data element entry is now visible in Object Navigator tree. Activate it.

13. The following code shows the usage of our newly created ABAP Dictionary type
Z_DOM_TYPE_USAGE

83
14. On executing the above code, it produces the following output.

Creating Structures

A structure (structured type) comprises components (fields). A component can refer to an


elementary type, another structure, a table type or a view.

1. Select Create  Dictionary Object  Structure from the context menu of


package, and enter structure name zstruct_type.
2. In Maintain Structure window enter the short description for zstruct_type.

3. Provide the name in column Component, enter the name of the type whose
attributes should be used in the component, you can enter any type here.

84
If you want to add components by entering the data type and length directly
choose this will enable the Data Type, Length Decimal Places
columns and Short Description.

By choosing you can switch to the screen for entering


references to existing types, this will enable the RType and Component Type
columns. If you enter a class, interface or generic reference (ANY, DATA or
OBJECT) in the Component Type column the RType field is automatically set. If
you enter a reference type already defined in the Dictionary as a reference type, a
blue arrow appears in the Data Type column.

If Data Type is QUAN or CURR then in Currency / Quantity tab page, you must
specify the reference table; this reference table must contain a field with the
format for the currency key (CUKY) data type or unit of measure (UNIT) data
type.

On Entry help/check tab, choose , if you want to assign a search


help to a structure field that points to a data element.

4. Then press SAVE, CHECK and ACTIVATE.


5. The following code shows the usage of our newly created zstruct_type.

85
6. On executing the above code, it produces the following output.

Inserting an Include

To include the components of existing structures into new structure at highest


hierarchy level, you can select EditIncludeInsert when creating the structure.
This function provides the same option as the INCLUDE statement in ABAP
programs in order to create structures with a single hierarchy level from other
structures. Structures that are defined in this way are particularly interesting as
templates for database tables.

In the example below a predefined structure SYST whose elements are the data types
of the system fields is included in the zstruct_type.

86
1. Place the cursor under the line in which you want to insert the include and
choose EditIncludeInsert.

2. A dialog box appears, enter the structure name SYST, the optional group name
(with group name, you can access the fields in the include together in ABAP
program) or a three-place suffix (suffix can be used to avoid name collisions
between fields of the include and fields already in the table). Press continue
button.

3. A line with .INCLUDE in the Component column and the name of the structure
is inserted into Component type column.

4. Click to Expend Include button to see the fields of SYST structure.

87
88
Operations in ABAP
Here we will look into the basic operations that we can carry out on data objects.

Assignment Operation
Assignment operation determines how to move the data into the data objects. The MOVE
statement and assignment operator (=) can be used to perform the assignment operation
on the data objects. To assign the value of a data object source to a variable
destination, use the following statement:

MOVE source TO destination.

Or the equivalent statement

destination = source.

In addition to the general type of assignment using Move or the assignment operator
(=), ABAP provides several special types of assignments.

Assigning Structures by Components: To assign individual components of a structure to


the components of another structure. One alternative method is to use several MOVE
statements but ABAP provides a special statement for this:

MOVE-CORRESPONDING source_struct TO destination_struct.

This statement identifies all components that have the same name in both structures and
assigns them individually according to the respective assignment rules without affecting
other components. Nested structures are completely dissolved in this process.

When it is executed, it is broken down into a set of MOVE statements, one for each pair of
fields with identical names, as follows:

MOVE source_struct-<ci> TO destination_struct-<ci>.

The following example shows that the components of a structure are assigned to the
components of two other structures that have the same names.

89
90
The above program produces the following output.

Formatted Assignment: The internal representation of data in data objects is usually not
suited for a direct output of the values to the user. In particular, this holds true for
numeric data in data objects of numeric data types whose code can not be used for a
direct presentation. Prior to displaying the contents of those data objects, they must be
converted into character-like data that can be output so that the user understands them.
ABAP provides WRITE TO assignment statement that explicitly carries out this.

WRITE source TO destination format_options.

This statement formats the content of an elementary data object source and assigns it to
a flat character –like data object, destination. If no format_options additions
are specified, formatting is carried out according to type-dependent predefined rules that
can also depend on user-specific values or regional settings. Following table illustrate the
different formatting options.

91
For All Data Types
Option Function
LEFT-JUSTIFIED Output is left-justified.
CENTERED Output is centered.
RIGHT-JUSTIFIED Output is right-justified.
If a field contains only zeros, these are replaced by blanks.
NO-ZERO For type C and N fields, leading zeros are replaced
automatically.
For Numeric Fields
NO-SIGN The leading sign is not displayed on the screen.
DECIMALS <d> <d> defines the number of digits after the decimal point.
EXPONENT <e> In type F fields, the exponent is defined in <e>.
ROUND <r> Type P fields are multiplied by 10**(-r) and then rounded.
CURRENCY <c> Format according to currency <c> in table TCURX.
For Date Fields
DD/MM/YY Separators as defined in user’s master record.
MM/DD/YY Separators as defined in user’s master record.
DD/MM/YYYY Separators as defined in user’s master record.
MM/DD/YYYY Separators as defined in user’s master record.
DDMMYY No separators.
MMDDYY No separators.
YYMMDD No separators.

Lastly, data types in ABAP Dictionary can be linked with specific function modules
(Conversion Routines or Conversion Exits). Conversion routines are used for formatting
content for output and for converting input into internal formats. A conversion routine
can be assigned to a domain in the ABAP Dictionary. These routines are automatically
executed when you use the WRITE TO statement.

The following code demonstrates the use of WRITE TO statement.

92
The above code produces the following output.

93
The CLEAR statement reset variables to their type-specific initial value.

CLEAR data_obj.

That is depending on the elementary data type, the content of data object is reset to initial
value discussed in data types section. The structure components are initialized in
accordance with their data type. All lines of an internal table are deleted while the
reference variable points to null reference.

The three cases determine the execution of the assignment operation:

• Compatibility: The source and destination data objects are compatible.


This means their data types match in all technical properties. During copy process
the content of source is transferred byte by byte into the target field
destination. The technical properties of an elementary data types are length
and number of decimal places. In structured types, the technical properties are
defined by the composition of substructures and elementary data types. The
technical properties of table types are the table category, line type and table key.
• Convertibility (Type Conversion): The source and destination data
objects are not compatible but convertible. This means that a conversion rule
between the data types is defined in ABAP. In this case, the content of source is
first converted according to the conversion rule before it is transferred into the
target field destination. But it must be noted that a conversion requires a
substantial amount of extra computing time.
• Incompatibility and Inconvertibility: If source and destination data
objects are neither compatible nor convertible, no assignment is possible. If this is
detected during the syntax check, a syntax error occurs; otherwise, an exception
will be raised.

Type Conversions

In ABAP, the rules for type conversions are designed in such a way that the largest
possible number of data types can be converted into each other without any error. The
basic rule says that the content of a source field must represent a reasonable value for the
data type of the target variable must always be fulfilled. It is pointless to allow
conversions between data types d and t or between elementary fields and internal tables.
Following are the conversion rules for different data types:

Elementary Data Types

There are 10 built-in elementary types. ABAP contains conversion rules between all
those types with the exception of types d and t, between which conversion doesn’t make
sense.

94
• Text-Type to Text-Type: During the conversion between text-type data objects of
data type c and string, the characters are transferred as left-aligned. If
necessary, target fields of type c are filled with space characters on the right-hand
side, or the right-hand side is truncated. For target fields of the string type, the
transferred characters determine the length. Here you should note that closing
spaces are transferred for source fields of the string type, not for those of type
c.
• Text-Type to Numeric: During the conversion of text-type data objects to
numeric data objects of data types i, p, and f, the content of the source field must
represent a number in an appropriate notation (mathematical, commercial or
scientific). The value of the number is converted into the internal representation
of the target field.
• Text-Type to Byte-Like: During the conversion of text-type data objects to byte-
like data objects of data type x and string, the content of the source field must
contain values in hexadecimal notation. Each character of the source field
determines the contents of a half-byte of the target field.
• Numeric to Numeric: During the conversion between numeric data objects, the
value of the source field is converted into the internal representation of the target
field. If necessary the value can be rounded.
• Numeric to Text-Type: During the conversion of numeric data objects to text-
type data objects, the value of the source field is represented in the target field as
a character string, either in commercial or in scientific notation, depending on the
data type. In a commercial notion, the plus/minus sign is placed after the number,
while the scientific notation consists of a mantissa and an exponent. If the target
field is not long enough, the value is either rounded or truncated.
• Numeric to Byte-Like: During conversion of numeric to byte-like data objects,
the value of the source field is first converted to i. Then, its internal
representation is transferred without further conversion.
• Byte-Like to Byte-Like: During the conversion between byte-like data objects, the
bytes are transferred as left-aligned. If necessary, target fields of type x are filled
with hexadecimal 0 on the right-hand side, or the right-hand side is truncated. For
target fields of the xstring type, the transferred bytes determine the length.
• Byte-Like to Text-Type: During the conversion of byte-like data objects to text-
type data objects, the values of the bytes of the source field are represented in
hexadecimal notation in the target field.
• Byte-Like to Numeric: During the conversion of byte-like data objects to numeric
data objects, the final four bytes of the source field are interpreted as an internal
representation of a data object of type i; this number is converted into the data
types of the target fields.

The following example demonstrates the elementary data types conversion.

95
96
When a plain number is entered, every conversion worked as:

When a character is entered the conversion is failed and an exception is caught.

97
Structured Data Types

There are no conversion rules for structures that contain internal tables or strings (deep
structures).

The conversion rules between flat incompatible structures state the following:

• Flat structures whose Unicode Fragment Views (UFV) are identical can be
assigned without prior conversion.
• Flat structures of different lengths whose initial sections have the same UFV
across the length of the shorter structure can be assigned without conversion in
the length of shorter structure. Surplus components are either truncated or they are
filled with type-specific initial values.

Note: UFV splits a structure into fragments. A fragment is a grouping of structure


components of the same or similar data types. In nested structures, the elementary
components on the lowest nesting depth are taken into account when forming fragments
in nested structures.

BEGIN OF struc,
a(2) TYPE C,
b(4) TYPE N,
c TYPE D,
d TYPE T,

98
e TYPE F,
f(2) TYPE X,
g(4) TYPE X,
h(8) TYPE C,
i(8) TYPE C,
END OF struc.

Fragment 1: a, b, c, d
Fragment 2: Alignment gap between d and e
Fragment 3: e
Fragment 4: f, g
Fragment 5: Alignment gap between g and h
Fragment 6: h, i

Alignment gaps are bytes that are inserted in front of components so that the required
alignment can be attained. The system normally aligns fields and structures
automatically when you declare them. Components with alignment requirements must
begin at address that can be divided by a specific number. For example, the address of a
type i field must be divisible by 4 and the address of a type f field by 8.

The conversion rules between flat structures and elementary fields state the following:

• If the structure is purely character-like, it is treated like a data object of type c


during the conversion.
• If the structure is not completely character-like, the elementary field must be of
type c, and the structure must begin with a character-like fragment that is at least
as long as the elementary field. The assignment occurs exclusively between this
fragment and the elementary field.

The following example demonstrates the structured type conversion.

99
The above code produces the following output.

This example defines two different structures, struct_1 and struct_2. In each one,
the first three components have the same data type. After assignment of struct_1 to
struct_2, only the result for the first three components is as if they had been

100
transferred component by component. All the remaining positions of struct_1 are
omitted.

Internal Tables

Internal tables can only be converted into other internal tables. You cannot convert them
into structures or elementary fields. Internal tables are convertible if their line types are
convertible. The convertibility of internal tables does not depend on the number of lines.

The conversion rules between internal tables state the following:

• Internal tables which have internal tables as their line type are convertible if the
internal tables which define the line types are convertible.
• Internal tables which have line types that are structures with internal tables as
components are convertible according to the conversion rules for structures if the
structures are compatible.

Reference Types

Class and Interface variables are pointers to objects. The conversion rules between
reference types state the following:

• If the two class references are incompatible, the class of the target field must be
the predefined empty class OBJECT.
• When you assign a class reference to an interface reference, the class of the
source field must implement the interface of the target field.
• If two interface references are incompatible, the interface of the target field must
contain the interface of the source field as a component.
• When you assign an interface reference to a class reference, the class of the
source field must be the predefined empty class OBJECT.

Arithmetic Operations
In arithmetic operations, numeric operands are linked to each other via arithmetic
operators. The numeric operands can be numeric data objects or built-in functions.

Numeric data objects are data objects of type i, f, p, decfloat16 and decfloat34
or byte-like (x) and character-like (c, d, t, n) data objects whose contents can be
interpreted as numeric on the basis of conversion rules.

Built-in functions are predefined functions with a numeric return value. Built-in functions
are further divided into numeric, floating point and description functions. Numeric
functions accept arguments of any type of numeric data i.e numeric functions are
overloaded. Floating point functions accept only arguments of floating point data and
returns floating point value. The description functions return properties of their argument

101
for example, charlen determines the length of characters in terms of bytes, strlen
defines the number of characters of data object and lines determine the number of lines
in an internal table.
The following table summarizes the numeric and floating point built in functions.

Function Meaning / Result


Numeric Functions
abs( x ) Returns an absolute value of an argument.
sign( x ) Returns the +/- sign of an argument.
ceil( x ) Returns the smallest integer value not smaller than
the argument.
floor( x ) Returns the largest integer value not larger than the
argument.
trunc( x ) Returns the integer part of an argument.
frac( x ) Returns the fraction part of an argument.
Floating Point Functions
acos( x ), asin( x ),
atan( x ) , cos( x ), Trigonometric functions.
sin( x ), tan( x)
cosh( x ), sinh( x ),
Hyperbolic functions.
tanh( x )
exp( x ) Exponential function with base e (e=2.7182818285).
log( x ) Natural logarithm with base e.
log10( x ) Logarithm with base 10.
sqrt( x ) Square root (only possible for positive numbers).

The following table provides the list of arithmetic operators. ABAP also provides a self
-explanatory statement for four basic arithmetic operations but we won’t elaborate on
these statements any further.

Operator Meaning Usage Statement


+ Addition p = n + m. ADD n TO m.
- Subtraction p = m – n. SUBTRACT n FROM m.
* Multiplication p = m * n. MULTIPLY m BY n.
/ Division p = m / n. DIVIDE m BY n.
DIV Integer division p = m DIV n. ---
MOD Remainder p = m MOD n. ---
** Exponent p = m ** n. ---

The following example shows the usage of arithmetic operators and built-in functions.

102
103
The above code produces the following output.

Logical Operations
A logical operation returns true or false. ABAP does not contain a Boolean data type to
accept these values. The missing Boolean data type is replaced with data objects of type
c and length 1. If the data object contains an “X”, it is interpreted as “true”. The “false”
value, on the other hand, is represented by a space character.

In majority of logical operations, the contents of two operands are compared with each
other by using a relational operator. ABAP provides generic relational operators for all
data types, logical linking and negating operators and specific relational operators for
certain data types. The following table summarizes these operators.

104
Operator Meaning Usage Statement
Generic Relation Operators
= Equal to EQ
<> Not equal to NE
< Less than LT
<= Less than or equal to LE
> Greater than GT
>= Greater than or equal to GE
Logical Linking and Negating Operators
Combine two logical ( c < n ) AND ( n
AND ---
expression > f )
Combine two logical ( c < n ) OR ( n >
OR ---
expression f )
NOT Negate the result of NOT ( c < n ) ---
logical expression
String Comparison Operators
CO Contains Only 'BD ' CO 'ABCD ' ---
CN Contains Not only 'ABC12' CN 'ABCD ' ---
CA Contains Any 'ABcde' CA 'Bd ' ---
NA contains Not Any 'ABAB ' NA 'AB ' ---
CS Contains String 'ABcde' CS 'bC ' ---
NS contains No String 'ABcde' NS 'ce ' ---
CP Contains Pattern 'ABcde' CP '*#b*' ---
NP contains No Pattern 'ABcde' NP '*b*' ---
Bit Sequences Comparison Operators (2nd operand must have type X)
O bits are One ‘a’ O <x> ---
Z bits are Zero ‘d’ Z <x> ---
M bits are Mixed ‘a’ M <x> ---

Numeric fields (i, f, p) are compared with each other with regard to their numeric
values. Character-like fields (c, string, d, t, n) are generally compared with each
other from left to right. Operands of type c and string are compared lexicographically
and by differentiating between uppercase and lowercase letters. Operands of type n are
compared on the basis of the represented numeric values. If operands have type d or t
and contain a valid date or time, the later date or time is greater than the earlier one. Byte-
like fields (x, xstring) are compared on the basis of their byte values.

The previous type conversion rules also apply to operands of logical operators with little
modifications. If one operand is date field type d or a time field of type t and the other

105
operand is a numeric field, the system converts date or time field into the numeric type. If
the other operand is character-like, the date and time fields are also regarded as being
character-like. If one of the operands has data type n and the other has data type c,
string, x or xstring, the contents of both operands are converted to data type p. If
one of the operands is a text field of type c and the other operand is a text string of type
string, the text field is converted into a string, the same rule applies to x and
xstring. If one of the operands has a byte-like type and the other operand has a
character-like type c or string, the content of an operand type x is converted to c,
while the content of an operand of type xstring is converted to string. It is
recommended that you use compatible operands.

Two reference variables are equal when they point to the same object. Two compatible
structures are identical if all their components are identical. Incompatible structures can
be compared with each other if their Unicode fragment views are identical in the length
of the shorter structure. Structures can be compared with elementary fields if they contain
only character-like and flat and its length matches at least the length of the elementary
field, which, in turn, must be of type c.

A prerequisite for comparing internal tables is that its line type can be compared. If two
internal tables contain the same number of lines, they are compared with each other line
by line and component by component.

Note: ABAP processes logical expressions from the left to right. It the system detects
that one of the partial expressions is fulfilled or not fulfilled no other comparisons checks
are carried out for this partial expression. Therefore, to increase the processing speed by
arranging logical expressions in such a way that comparisons that often return a
‘”false” are placed at the beginning of an AND sequence.

Logical Expressions with Predicates

ABAP provides the following predicates for logical expressions.

[NOT] BETWEEN: check whether the value of a field lies within a particular range. For
example; number BETWEEN 3 AND 7.

IS [NOT] INITIAL: check whether the value of a field is initial. For example; flag IS
INITIAL.

IS [NOT] BOUND: check whether a reference variable points to an object. For example;
ref IS BOUND.

IS [NOT] ASSIGNED: check, whether a memory area is assigned to a field symbol


<fs>. Field symbols are placeholders for existing data objects. For example; <fs> IS
NOT ASSIGNED.

106
IS [NOT] SUPPLIED: check whether an actual parameter is bound to a formal
parameter of a procedure. This predicate can only be used in function modules and
methods. For example; p1 IS SUPPLIED.

[NOT] IN selection_tbl: Evaluates the conditions in a selection table. A selection table is


an internal table with standard table type, standard which represents a logical condition.
The row type of a selection table is a structure that consists of four components: sign,
option, low , and high. The following statement is used to declare a selection table
in the program that is linked to the f column of a database table, or to an internal f field
in the program.

SELECT-OPTIONS sel_tab FOR f.


“I for inclusive and E for exclusive.
sel_tab-sign = ‘I’.
“Selection operator, EQ, NE, GT, LE, LT, CP and NP
sel_tab-option = ‘EQ’.
“same as the column type of the database table, to which
“the selection criterion is linked. Specify the lower limit
“for a range selection.
sel_tab-low = 3.
“same as the column type of the database table, to which
“the selection criterion is linked. Specify the upper limit
“for a range selection.
sel_tab-high = 7.

107
Control Structures
Control structures decompose a processing block (method etc.) into statement blocks and
control the program flow within the processing block. ABAP provides Selection or
Branching control structures and looping control structures. The concept of ABAP
control structures is similar to those of other programming languages.

Selection / Branching Control Structures


ABAP has two types of selection structures i.e. IF control structure and CASE control
structure.

IF Control Structure

The IF control structure is used to execute only one statement block on the basis of
logical expression. Following is the general syntax of IF control structure.

IF log_exp1.
statement_block1
[ELSEIF log_exp2].
statement_block2
.....................
.....................
[ELSE].
statement_blockn
ENDIF.

The logical expressions log_exp are checked from top to bottom, starting with the IF
statement. The statement block that is located after the first true logical expression is
executed. If none of the logical expressions is true, the statement block after the ELSE
statement is executed. If the ELSE statement is not specified, it may result in no
statement block being executed. However, it is recommended to always close the IF
control structure with an ELSE statement.

Listing below shows an example of IF control structure.

108
109
The above code produces the following output.

CASE Selection Structure

The CASE selection structure is a multi-way branch control statement. Following is the
general syntax of CASE control structure.

CASE data_obj.
WHEN operand1 [OR operand2] [OR operand3 ……]].
statement_block1
WHEN opernad4 [OR operand5] [OR operand6 ……]].

110
statement_block2
.....................
.....................
WHEN OTHERS.
statement_blockn
ENDCASE.

The system checks from top to bottom, starting with the first WHEN statement, whether
the contents of the operand operand agree with the contents of one of the operands,
operand1, operand2, …, and processes the statement block following the first
agreement. If no agreement is found, the statement block after WHEN OTHERS statement
is executed. If the WHEN OTHERS statement is not specified, it may result in no
statement block being executed. However, it is recommended to always close the CASE
control structure with WHEN OTHERS statement.

Listing below shows an example of CASE control structure.

111
The above code produces the following output.

112
Loops / Iterative Control Structures
Loops enable to execute a statement block several times. ABAP provides DO, WHILE,
LOOP AT and SELECT loop.

DO Loop

DO loop executes the block of statements several times unconditionally, Following is the
syntax of DO loop.

DO [n TIMES].
statement_block
ENDDO.

If no additions are specified, the statement block is repeated until it reaches a termination
statement such as EXIT or STOP. The system field SY-INDEX contains the number of
loop passes, including the current loop pass. In nested loop you can access the index of an
outer loop from within the inner loop by using the auxiliary variable.

The TIMES addition restricts the number of loop passes to n. n can be literal or a
variable. If n is 0 or negative, the system does not process the loop. If you do not use the
TIMES option, you must ensure that the loop contains at least one EXIT or STOP
statement to avoid endless loops.

Code below shows an example of DO loop.

113
114
The above listing produces the following output.

WHILE Loop

WHILE loop allows a block of code to be executed while a specified condition is true.
Following is the syntax of WHILE loop.

WHILE log_exp.
statement_block
ENDWHILE.

The statement block in the loop is repeatedly executed as long as the logical expression
log_exp is true, or until the loop is left using a statement such as EXIT. Here as well,
sy-index is set to the current loop index in each pass.

Code below shows an example of WHILE loop.

115
The above listing produces the following output.

LOOP AT Loop

LOOP AT is special type of loop which can be used to read lines from internal table
sequentially. Following is the syntax of LOOP AT loop.

116
LOOP AT internal_tab result [conditions].
statement_block
ENDLOOP.

The statement block between LOOP and ENDLOOP is executed once for each line. The
output result determines when and where the line contents are read. To restrict the
number of lines use the conditions addition. The loop continues to run until all the
table lines that meet condition have been read or, or until the loop is left using a statement
such as EXIT. The LOOP statement sets system field sy-tabix to table index of the
current table line for standard tables and sorted tables and to 0 for hashed tables, after
every loop pass while the sy-subrc remains unchanged.

There are four alternatives to influence the output result as:

... {INTO wa} |


{ASSIGNING <fs>} |
{REFERENCE INTO dref} |
{TRANSPORTING NO FIELDS} ...

• If you specify INTO wa (Work area), the contents of the line are transported to
data object wa. The data type of the data object must be compatible with the line
type of the internal table.
• If you specify ASSIGNING <fs> (Field Symbol), no values will be transported.
Instead, the field symbol is bound to the table line in memory after the
assignment. In turn, the table line can be evaluated or modified using <fs>.
• If you specify REFERENC INTO dref, no values will be transported either.
Instead, the data reference variable dref points to the table line the memory after
the statement. The table line can be evaluated or modified using dref->…
• If you specify TRNASPORTING NO FIELDS, you only fill the corresponding
system fields. This addition is only possible, if the addition WHERE is used
simultaneously in the conditions.

Note: Field symbol (fs) is placeholder or symbolic name for other fields. They do not
physically reserve space for a field, but point to its contents. A field symbol can point to
any data object. The data object to which a field symbol points is assigned to it after it
has been declared in the program. You must assign a field to each field symbol before
you can address the latter in programs. Field symbols are similar to dereferenced
pointers in C.

To limit the rows in the output the conditions given below can be used:

... [FROM index1] [TO index2] [WHERE log_exp].

• If FROM index1 is specified, lines starting from table index index1 will be
accepted. For index1 data object of type i is expected. If value of index1 is

117
smaller or equal to 0, then it will be set to 1. If the value is larger than the number
of table rows, the loop is not passed through. FROM index1 is only possible
with standard and sorted tables.
• If TO index2 is specified, lines after table index index2 will be accepted.
For index2 data object of type i is expected. If value of index2 is smaller or
equal to 0, then the loop will not be passed. If the value is larger than the number
of table rows, the value will be set to the number of rows. If index2 is smaller
than index1 then the loop is not passed as well. TO index2 is only possible with
standard and sorted tables.
• If WHERE log_exp is specified, lines fulfilling the log_exp will be accepted.
First operand of any comparison will be component of an internal table. WHERE
log_exp is possible with all table types.

Code below shows an example of LOOP AT loop.

118
119
The above listing produces the following output.

SELECT Loop

The SELECT loop reads several entries of a database table in succession. Following is
the syntax of SELECT loop.

SELECT result FROM dbtab|dbview


INTO [CORRESPONDING FIELDS OF]
work_area|(dobj1,dobj2,...)]|
INTO|APPENDING [CORRESPONDING FIELDS OF] TABLE itab
WHERE conditions].

statement_block

ENDSELECT.

The result defines whether the resulting set consists of multiple rows (table-like
structure) or a single row (flat structure). It specifies the columns to be read and defines
their names in the resulting set. The conditions addition restricts the number of lines.

120
For every loop pass, the SELECT statement assigns a row to the data objects specified in
INTO addition. If the last row was assigned or if the result set is empty, then SELECT
branches to ENDSELECT. We can end the loop using the statement such as EXIT.

The SELECT statement sets sy-subrc to 0 for every pass by value to an ABAP data
object and to 4 if the result set is empty. After every value that is transferred to an ABAP
data object, the SELECT statement sets sy-dbcnt to the number of rows that were
transferred. If the result set is empty, sy-dbcnt is set to 0.

The following listing shows an example of SELECT loop.

121
122
After selecting “New York” on the selection screen, the following out put is produced.

123
Field Symbols
Field symbols are placeholders or symbolic names for other fields. They do not
physically reserve space for a field, but point to its contents. A field symbol can point to
any data object. The data object to which a field symbol points is assigned to (ASSIGN)
it after it has been declared in the program.

After its declaration, a field symbol is initial - that is, it does not reference a memory
area. After successful assignment, there is no difference in ABAP whether you reference
the field symbol or the field itself.

Field symbols are similar to dereferenced pointers in C (*ptr). Field symbols can also
be compared to a data reference variable that is dereferenced with ->*. All operations
programmed with field symbols are applied to the field assigned to it.

We can declare field symbol as:

FIELD-SYMBOLS <FS> [TYPE type|LIKE dobj].

The FIELD-SYMBOLS statement is used to declare the field symbols. For field symbols,
the angle brackets are part of the syntax. They identify field symbols in the program
code.

The TYPE addition allows you to specify the type of a field symbol. If you do not specify
any additions, the field symbol <FS> can have data objects of any type assigned to it.
When you assign a data object, the field symbol inherits its technical attributes. The data
type of the assigned data object becomes the actual data type of the field symbol.

Field symbols allow working generically with data objects, that is, we can program
operations without knowing the data objects with which the program will actually work
at runtime. Secondly, we can use field symbols for the casting of data objects.

The following listing demonstrates the field symbols.

124
The above code produces the following code.

125
Static Assignment and Subfield Addressing
If the name of the data object that is being assigned to the field symbol is already known
when the program is created it is referred as static assignment. During static assignment
not only we can assign entire data objects to a field symbol, but also we can assign
subfields of byte or character type data objects which we specify using the offset and
length specifications. The syntax is:

ASSIGN dobj[+offset][(length)] TO <fs>.

Listing below demonstrate the use of subfield addressing.

After executing the above code the following out put is produced.

126
Dynamic Assignment
If the name of the data object that we want to assign to a field symbol is not known until
runtime, we can use the following variant of the ASSIGN statement:

ASSIGN (name) TO <fs>.

As a result of using the above statement, the data object whose name is contained in the
name field in brackets is assigned to the field symbol <fs>. After dynamic assignment,
we must always check sy-subrc before we access the field symbol. If the assignment
is successful, sy-subrc is set to 0, if no data object with the right name is found there
is no assignment to the field symbol and sy-subrc is set to the value 4.

In the example in listing below in main method we dynamically access the attribute
attr of the class lcl_cls. Here both the name of the class and the name of the
attribute are given in the character type fields attr_name and cls_name.

127
The above code produces the following output.

Component Assignment

To dynamically address the components of structure,


use the following variant of ASSIGN statement.

128
ASSIGN COMPONENT comp OF STRUCTURE struct
TO <fs>.
If comp is a data object of the type c or string, its
content is interpreted as the name of the component.
If the comp has a different type and if the content is
a number, this specifies the number of the
component.
In the example below the field symbol <f1> points to
the structure struct, <f2> points to the field
comp. In the DO loop the components of struct
are specified by their numbers and assigned one by
one to <f3>. After the loop the component col3 of
struct is specified by its name and assigned to
<f3>. Note, expressions such as <f1>-col1 are
syntactically incorrect.

129
The above code produces the following output.

130
Increment Assignment

It is possible within a structure to incrementally access


subfields of the structure. Following is the syntax
for increment assignment.
ASSIGN dobj INCREMENT inc TO <fs> [RANGE
range].
A memory area is assigned to the field symbol that is
exactly as long as the data object dobj and is offset
inc times this length of dobj. With RANGE, we can
specify the area within which an assignment is
possible. Here, range is a data object that
comprises the subareas. Without specifying RANGE,
we can only access the memory area within dobj
itself. The example in listing below shows how
within a character-type structure txt, starting
from the two-character component comp1,
subfields of the component comp2 are accessed that
are just as long.

131
The above code produces the following output.

132
Casting Type in Assignment
When we assign data objects to field symbols, a cast can be performed on any data types.
This means that the assigned memory area can be handled assuming a particular type.
The addition CASTING allows to assign data objects to field symbols whose type is not
compatible with the typing of the field symbol. Without explicit casting with the addition
CASTING, the field symbol always takes over the type of the specified data object, which
must then be compatible with the typing of the field symbol.

If the field symbol is typed either fully or with one of the built-in generic ABAP types c,
n, p or x (Implicit Type Specification), the following form of the ASSIGN statement can
be used:

ASSIGN dobj TO <fs> CASTING.

The assigned memory area is cast to the type of the field symbol. The listing given below
the content of the character-type system field sy-datum is interpreted as a structure.

133
The above coding produces the following output.

If the field symbol is typed generically, rather than completely (Explicit Type
Specification), we can use the following form of ASSIGN statement.

ASSIGN f TO <fs> CASTING TYPE typ|(nemae) | LIKE dobj


| TYPE HANDLE handler.

Behind TYPE, we can specify a name of a data object enclosed in round brackets; this
then specifies the data type dynamically. The TYPE HANDLE addition specify a
reference to a type object of the Run Time Type Services (RTTS), which allows an
entirely dynamic casting, because such a type object can be created through the definition
of a new data type.

The specified data type must be compatible with the generic typing of the field symbol. It
can preserve or specialize the generic typing but it can not overwrite an already known
technical property of the field symbol. The explicit type specification is forbidden for a
fully typed field symbol.

Listing below shows an example in which the numerical content of a text field is
interpreted once as a date and once as a number value. The interpretation occurs when the
field symbol is assigned to an integer field, where the data type of the field symbol
determines the conversion rule.

134
The above coding produces the following output.

135
Note: We can use the <fs> IS ASSIGNED to check whether a data object is assigned
to a field symbol. The expression will be true if the field symbol <fs> points to a data
object. While we can us the UNASSIGN <fs> statement to ensure that no more data
objects are assigned to a field symbol. On the other hand, the CLEAR <fs> statement
doesn’t mean that the field symbol will be initialized, but rather the memory area that
was assigned to the field symbol.

136
Internal Tables
The data objects of table types are internal tables. Internal tables allow storing a variable
amount of data of a fixed structure in the memory and enable to efficiently use this data.
In ABAP, internal tables fulfill the function of arrays. We can use internal tables
whenever we want to process a dataset with a fixed structure within a program. A
particularly important use for internal tables is for storing and formatting data from a
database table within a program. We can use internal tables to perform table calculations
on subsets of database tables. For example, you can read a certain part of a database table
into an internal table. From the internal table, you can then calculate totals or generate a
ranked list.

Like all elements in the ABAP type concept, internal tables can exist both as data types
and as data objects. Internal tables are implicitly managed by the runtime environment.
ABAP contains a set of special, highly optimized statements that we can use when
working with internal tables. The following syntax can be used to declare the internal
tables.

DATA tab_name TYPE|LIKE STANDARD|SORTED|HASHED TABLE


OF data_type|data_object WITH [NON-]UNIQUE KEY col1…
coln [INITIAL SIZE n].

TYPES tab_name TYPE STANDARD|SORTED|HASHED TABLE


OF data_type WITH [NON-]UNIQUE KEY col1…coln
[INITIAL SIZE n].

Internal tables are stored in individual blocks in the memory. The [INITIAL SIZE
n] addition enables to specify initially required number of table lines n. It is
recommended that specify initial memory requirement only when the number of entries
in table is already known. This can be particularly important for internal tables that are
themselves components of tables and contain only a few lines.

Internal tables contain three essential attributes: Row/Line Type, Table Category and
Table Key.

Row/Line Type

The line type of an internal table can be any data type. The data type of an internal table
is normally a structure. Each component of the structure is a column in the internal table.
However, the line type may also be elementary or another internal table.

Table Category

137
The table category determines the way an internal table is internally managed and the
way in which it is accessed within the ABAP program. It doesn’t affect an access to
entire table, as it occurs for instance in assignment and comparisons. There are three
categories of internal tables.

• STANDARD Table: is managed internally by a table index. Access is possible via


table index or table key. With a key access, the response time is directly
dependent on the number of table entries. The key of a standard table is always
non-unique. This table category is suited best whenever the individual entries can
be accessed using the index. A table index numbers the lines from 1 to the
existing number of lines. The system field sy-tabix is always filled with the
index of the line that is addressed.
• SORTED Table: is managed internally by means of a table index, too. They are
always sorted by the table key and can be accessed via the table index or the table
key. With a key access, the response time is logarithmically dependent on the
number of table entries, because the table is accessed via a binary search. The key
of sorted tables can be unique or non-unique. This table category is suited
whenever the table must already be sorted when it is filled. The system field sy-
tabix is always filled with the index of the line that is addressed.
• HASHED Table: is managed internally by a hash algorithm. Hashed tables can be
accessed only via the table key. The response time is constant, independent of the
number of table entries. The key of hashed tables is always unique. This table
category is suited whenever the key accesses represent the central operation on
the table entries.

Which table category to use depends upon the type of operations you want to perform on
the table and how often you want to access the table in your program?

• Standard tables are the most appropriate type if you are going to address the
individual table entries using the index. Index access is the quickest possible
access. You should fill a standard table by appending lines (APPEND statement),
and read, modify and delete entries by specifying the index (INDEX option with
the relevant ABAP command). The access time for a standard table increases in a
linear relationship with the number of table entries. If you need key access,
standard tables are particularly useful if you can fill and process the table in
separate steps. For example, you could fill the table by appending entries, and
then sort it. If you use the binary search option with key access, the response time
is logarithmically proportional to the number of table entries. We should avoid
using large standard tables of more than 100 lines because of the linear search
process.
• Sorted tables are useful if both a fast key access and an index access are necessary
and if the lines should already be sorted during the filling of the table. You fill
sorted tables using the INSERT statement. Entries are inserted according to the
sort sequence defined through the table key. Any illegal entries are recognized as
soon as you try to add them to the table. The response time for key access is
logarithmically proportional to the number of table entries, since the system

138
always uses a binary search. Sorted tables are particularly useful for partially
sequential processing in a LOOP if you specify the beginning of the table key in
the WHERE condition.
• Hashed tables are the most appropriate type for any table where the main
operation is key access. You cannot access a hashed table using its index. The
response time for key access remains constant, regardless of the number of table
entries. Like database tables, hashed tables always have a unique key. Hashed
tables are useful if you want to construct and use an internal table which
resembles a database table or for processing large amounts of data.

Table Key

The table key identifies table rows. There are two kinds of key for internal tables - the
standard key or default key and a user-defined key. The key should be UNIQUE or NON-
UNIQUE. For all table categories, we can specify one of the following key definitions
during the declaration:

• If a table has a structured line type, its default key consists of all of its non-
numerical (i,f,p) columns/components that are not references or themselves
internal tables.
• If a table has an elementary line type, the default key is the entire line (pseudo-
component table_line, the entire line of the internal table is interpreted as the
only component.).
• If a table has an internal table line type, the default key is empty.

The user-defined key can contain any columns/components of the internal table that are
not references or themselves internal tables. Internal tables with a user-defined key are
called key tables. When you define the key, the sequence of the key fields is significant.
You should remember this, for example, if you intend to sort the table according to the
key.

Working with Internal Tables


When working with internal tables, we must distinguish between the access to single
lines and the access to the entire table.

Processing Single Lines

When working with single table lines, we must distinguish between the operators that are
possible for all table types, and those that are only possible with index tables. Index
tables (standard and sorted tables) have an internal index, making linear access possible.
Hashed tables have no linear index. Consequently, only key access is possible. The
operations that are permitted for all table types do not use indexes.

139
The statements used to access lines of any type of table differ from those used to access
index tables mainly through the TABLE addition following the corresponding keyword.
For example, you would use MODIFY to change lines in index tables, but MODIFY
TABLE to change lines in any type of table.

There are three ways to access a single table entry: Access Using a Work Area, Access
Using Field Symbols and Access via Data References.

Access Using a Work Area: When we access individual table entries using a work area,
we are not working directly with the data in the table. Instead, we work with another data
object as a work area. The work area is an interface to the entries in the internal table, and
must be convertible into the line type of the internal table. When we read data from a
table record, the data you are reading overwrites the current contents of the work area.
You can then use this data in the program. When you write data to the internal table, this
must first be placed in the work area. The system then transfers it from the work area to
the appropriate table entry.

Access Using Field Symbols: When we access an internal table using a field symbol , we
do not need to copy the data into a work area. We can assign a line of an internal table to
a field symbol. Ideally, the field symbol will have the same type as the line type of the
internal table. Once you have assigned the entry to the field symbol, working with the
field symbol has exactly the same effect as accessing the corresponding line directly.

Access via Data References: When we access an internal table using a data reference,
we do not need to copy the data into a work area. We can assign a line of an internal table
to a data reference. Ideally, the data reference will have the same type as the line type of
the internal table. Once we have assigned the entry to the field symbol, working with the
dereferenced data reference has exactly the same effect as accessing the corresponding
line directly.

Inserting Rows

To fill an internal table with lines, we must us the INSERT statement as:

INSERT {wa|INITIAL LINE|LINES OF tab_name [FROM idx1] [TO


idx2]}
INTO {TABLE itab_name | itab_name [index idx]}
[ASSIGNING <fs> [CASTING] | REFERENCE INTO dref].
The wa represents the work area, a new line is generated and filled with the contents of
wa. wa must be compatible with the line type of the internal table when you insert the
lines or work area using the table key. The INITIAL LINE statement represents a new
line in which each component contains the type-specific initial value. The LINES OF
tab_name [from idex1] [TO idx2] specify the internal table from where the
lines are inserted one after another according to the same rules as for the insertion of a
work area. The line types of both itab_name and tab_name must be compatible. If

140
tab_name is an index table, you can specify FROM idx1 and TO idx2 to restrict the
lines to be inserted.

The addition TABLE specifies the position at which the line is inserted, which is specified
using the table key. If we use the addition INDEX, the table index is used for the
specification. The INDEX option can only be used for index tables.

• For standard tables, each new line is appended as the last line in the internal table
regardless of the table key and the table index of the following lines is increased
by one.
• For sorted tables, each new line is inserted into the sort order of the internal table
according to its key values. If the internal table does not have a unique key,
duplicate entries are inserted before the existing line.
• For hashed tables, each new line is inserted into the internal table by the hash
administration according to its key values.

The additions ASSIGNING <fs> [CASTING] | REFERENCE INTO dref can


only be used when inserting single lines. If they are inserted successfully, the inserted
line is assigned to a field symbol <fs> or a reference is set to the inserted line in the
reference variable.

On successful execution the system field sy-subrc is set to 0 or to 4 on failure.


Example below demonstrates the use of the INSERT statement.

REPORT z_itb_insert.

CLASS example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS.

CLASS example IMPLEMENTATION.


METHOD main.

"declare line types


DATA: int TYPE i,
dref TYPE REF TO i.

"declare internal tables


DATA: int_tab LIKE STANDARD TABLE OF int,
ref_tab LIKE HASHED TABLE OF dref
WITH UNIQUE KEY table_line.

DO 5 TIMES.
"insert table index in standard table
"and set the reference of inserted line
"into dref reference variable
INSERT sy-index
INTO int_tab INDEX 1
REFERENCE INTO dref.

141
"now insert the references to lines
"in hashed table using the table key
INSERT dref
INTO TABLE ref_tab.
ENDDO.

"print out the contents of standard table


WRITE 'Contnets of Standard Table'.
"output blank line
SKIP.

LOOP AT int_tab INTO int.


WRITE: int, space.
ENDLOOP.

SKIP 2.

"print out the contents of hashed table


"using derefernce operator
WRITE 'Contnets of Hashed Table'.

SKIP.

LOOP AT ref_tab INTO dref.


WRITE: dref->*, space.
ENDLOOP.

ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
example=>main( ).

The above coding produces the following output.

In the following example a structure is used as a line type.

REPORT z_itb_insert02.

CLASS example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS.

142
CLASS example IMPLEMENTATION.
METHOD main.

DATA: BEGIN OF line,


id TYPE i,
name TYPE c LENGTH 10,
age TYPE i,
weight TYPE p DECIMALS 2,
END OF line.

DATA itab LIKE SORTED TABLE OF line


WITH UNIQUE KEY id.

line-id = 1. line-name = 'Asghar'.


line-age = 20. line-weight = '80.00'.

INSERT line INTO TABLE itab.

line-id = 2. line-name = 'Salim'.


line-age = 18. line-weight = '76.23'.

INSERT line INTO TABLE itab.

line-id = 3. line-name = 'Ajmal'.


line-age = 15. line-weight = '82.00'.

INSERT line INTO TABLE itab.

line-id = 4. line-name = 'Shumila'.


line-age = 10. line-weight = '34.00'.

INSERT line INTO TABLE itab.

line-id = 5. line-name = 'Hamad'.


line-age = 16. line-weight = '67.00'.

INSERT line INTO TABLE itab.

WRITE: ' ID', 'Name',


' Age',
' Weight'.

SKIP 1.

LOOP AT itab INTO line.


WRITE: / line-id, line-name,
line-age, line-weight.
ENDLOOP.

ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
example=>main( ).

143
The above listing produces the following output.

The example below creates two internal tables with the same line type but different table
types. Each is filled with three lines. Then, itab is sorted into sorted table jtab.

REPORT z_itb_insert03.

CLASS example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS.

CLASS example IMPLEMENTATION.


METHOD main.

DATA: BEGIN OF row,


col1 TYPE c LENGTH 10,
col2 TYPE c LENGTH 10,
END OF row.

DATA itab LIKE STANDARD TABLE OF row.


DATA jtab LIKE SORTED TABLE OF row
WITH NON-UNIQUE KEY col1 col2.

row-col1 = 'Asghar'.
row-col2 = 'MS-IT'.
INSERT row INTO TABLE itab.

row-col1 = 'Saleem'.
row-col2 = 'BCS'.
INSERT row INTO TABLE itab.

row-col1 = 'Ajmal'.
row-col2 = 'FA'.
INSERT row INTO TABLE itab.

INSERT LINES OF itab INTO TABLE jtab.

WRITE: 'Table Index',


' Col1',
' Col2'.
WRITE: / '---------------------------------'.

LOOP AT jtab INTO row.

WRITE: / sy-tabix, ' ',

144
row-col1, row-col2.
ENDLOOP.

ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
example=>main( ).

The above listing produces the following output.

Inserting Aggregated Rows

The COLLECT statement is specifically used for totaling numeric values that belong to
unique keys. When the line is inserted, the system checks whether there is already a table
entry that matches the key. If there is no corresponding entry already in the table, the
COLLECT statement has the same effect as inserting the new line. If an entry with the
same key already exists, the COLLECT statement does not append a new line, but adds
the contents of the numeric fields in the work area to the contents of the numeric fields in
the existing entry. Following is the syntax of the COLLECT statement.

COLLECT wa INTO itab [ASSIGNING <fs> [CASTING] |


REFERENCE INTO dref].

The statement inserts the contents of a work area wa either as single row into an internal
table itab or adds the values of its numeric components to the corresponding values of
existing rows with the same key. The wa must be compatible with the row type of itab
and all components that are not part of the table key must have a numeric data type (i, p,
f).

The COLLECT statement is primarily used for hashed tables. In contrast, its use for
standard tables is error-prone and obsolete.

The example below demonstrates COLLECT statement.

REPORT z_itb_collect01.

CLASS example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS.

145
CLASS example IMPLEMENTATION.
METHOD main.

DATA: BEGIN OF line,


col1 TYPE c LENGTH 3,
col2 TYPE n LENGTH 2,
col3 TYPE i,
END OF line.

DATA itab LIKE SORTED TABLE OF line


WITH NON-UNIQUE KEY col1 col2.

line-col1 = 'abc'.
line-col2 = '12'.
line-col3 = 3.

COLLECT line INTO itab.


WRITE: 'sy-tabix: ', sy-tabix.

line-col1 = 'def'.
line-col2 = '34'.
line-col3 = 5.

COLLECT line INTO itab.


WRITE: / 'sy-tabix: ', sy-tabix.

line-col1 = 'abc'.
line-col2 = '12'.
line-col3 = 7.

COLLECT line INTO itab.


WRITE: / 'sy-tabix: ', sy-tabix.

WRITE / '------------------------------'.

LOOP AT itab INTO line.


WRITE: / line-col1, line-col2, line-col3.
ENDLOOP.

ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
example=>main( ).

The example fills a sorted table. The first two COLLECT statements work like normal
insertion statements. In the third COLLECT statement, the first line of itab is modified.
The following diagram shows the three steps:

146
In the example below compressed insertion of data from the database table sflight
into the internal table seats_tab. The rows in which the key components carrid and
connid are identical are compressed by adding the number of occupied seats to numeric
component seatsocc.

REPORT z_itb_collect02.

CLASS example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS.

CLASS example IMPLEMENTATION.


METHOD main.

DATA: BEGIN OF seats,


carrid TYPE sflight-carrid,
connid TYPE sflight-connid,
seatsocc TYPE sflight-seatsocc,
END OF seats.

DATA seats_tab LIKE HASHED TABLE OF seats


WITH UNIQUE KEY carrid connid.

SELECT carrid connid seatsocc


FROM sflight
INTO seats.
COLLECT seats INTO seats_tab.
ENDSELECT.

WRITE: 'Airline Code',


' Fligt Connection No.',
' Occupied Seats in Economy Class'.
SKIP.

LOOP AT seats_tab INTO seats.

147
WRITE: / seats-carrid, ' ',
seats-connid, ' ',
seats-seatsocc.
ENDLOOP.

ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
example=>main( ).

The above code produces the following output.

Appending Rows

The APPEND statement appends one or more rows to an internal index table (standard
and sorted tables) as last row(s). Following is the syntax of APPEND statement.

APPEND {wa|INITIAL LINE|LINES OF tab_name [FROM idx1] [TO


idx2]}

148
TO itab [SORTED BY comp] [ASSIGNING <fs>
[CASTING]|REFERENCE INTO dref].

The SORTED BY addition is used to sort the table in a specified way. It is allowed only
if you specify a workarea wa and if you use a standard table, where wa must be
compatible to the row type of the table. This statement provides a convenient way to fill
standard tables with lines. In standard tables, rows are appended directly and without
checking the content of the internal table while in sorted tables, rows are appended only if
they correspond to the sort sequence and do not create duplicate entries with unique table
key. Otherwise, an untreatable exception is triggered. No rows can be appended in hashed
tables. The APPEND statement sets sy-tabix to the table index of the last appended
row.

REPORT z_itb_append01.

CLASS example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS.

CLASS example IMPLEMENTATION.


METHOD main.

DATA: BEGIN OF line1,


col1 TYPE c LENGTH 3,
col2 TYPE n LENGTH 2,
col3 TYPE i,
END OF line1.

DATA tab1 LIKE TABLE OF line1.

DATA: BEGIN OF line2,


field1 TYPE c LENGTH 1,
field2 LIKE tab1,
END OF line2.

DATA tab2 LIKE TABLE OF line2.

line1-col1 = 'abc'. line1-col2 = '1'. line1-col3 = 10.


APPEND line1 TO tab1.

line1-col1 = 'def'. line1-col2 = '2'. line1-col3 = 11.


APPEND line1 TO tab1.

line2-field1 = 'ABC'. line2-field2 = tab1.


APPEND line2 TO tab2.

"Deletes all rows of the internal table, the memory space


"required for the table is freed up to the initial memory
"size INITIAL SIZE
REFRESH tab1.

line1-col1 = 'ghi'. line1-col2 = '3'. line1-col3 = 12.

149
APPEND line1 TO tab1.

line1-col1 = 'jkl'. line1-col2 = '4'. line1-col3 = 13.


APPEND line1 TO tab1.

line2-field1 = 'DEF'. line2-field2 = tab1.


APPEND line2 TO tab2.

"note the use of nested loop


LOOP AT tab2 INTO line2.

WRITE: / 'tab2-field1 = ', line2-field1.

WRITE / 'tab2-field2 = '.


LOOP AT line2-field2 INTO line1.

WRITE: / ' ',


line1-col1, line1-col2, line1-col3.
ENDLOOP.

SKIP.

ENDLOOP.
ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
example=>main( ).

The example above creates two internal tables tab1 and tab2. tab2 has a deep
structure because the second component of line2 has the data type of internal table
tab1. line1 is filled and appended to tab1. Then, line2 is filled and appended to
tab2. After clearing tab1 with the REFRESH statement, the same procedure is
repeated. Following is the output of the above example.

150
This example below creates two internal tables of the same type, itab and jtab. In the
DO loop, itab is filled with a list of square numbers, and jtab with a list of cube
numbers. Then, the last two lines of jtab are appended to itab.

REPORT z_itb_append02.

CLASS example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS.

CLASS example IMPLEMENTATION.


METHOD main.

DATA: BEGIN OF line,


col1 TYPE c LENGTH 1,
col2 TYPE i,
END OF line.

DATA: itab LIKE TABLE OF line,


jtab LIKE itab.

DO 3 TIMES.

line-col1 = sy-index.
line-col2 = sy-index ** 2.
APPEND line TO itab.

line-col1 = sy-index.
line-col2 = sy-index ** 3.
APPEND line TO jtab.

ENDDO.

APPEND LINES OF jtab FROM 2 TO 3 TO itab.

WRITE: 'Index', ' Sqr/Cube'.

LOOP AT itab INTO line.


WRITE: / line-col1, line-col2.
ENDLOOP.

ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
example=>main( ).

The above listing produces the following output.

151
The program below inserts three lines into the internal table itab using the APPEND
statement and the SORTED BY addition. The line with the smallest value for the field
COL2 is deleted from the table, since the number of lines that can be appended is fixed to
2 through the INITIAL SIZE addition.

REPORT z_itb_append03.

CLASS example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS.

CLASS example IMPLEMENTATION.


METHOD main.

DATA: BEGIN OF line,


col1 TYPE i,
col2 TYPE i,
col3 TYPE i,
END OF line.

DATA itab LIKE TABLE OF line INITIAL SIZE 2.

line-col1 = 11. line-col2 = 22. line-col3 = 55.


APPEND line TO itab SORTED BY col2.

line-col1 = 12. line-col2 = 23. line-col3 = 56.


APPEND line TO itab SORTED BY col2.

line-col1 = 13. line-col2 = 24. line-col3 = 57.


APPEND line TO itab SORTED BY col2.

WRITE: ' Col1', ' Col2',


' Col3'.

SKIP.

LOOP AT itab INTO line.

152
WRITE: / line-col1, line-col2, line-col3.
ENDLOOP.
ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
example=>main( ).

Following is the output of the above program.

Reading Rows

To read the contents of individual rows from an internal table, we can use the READ
TABLE statement. The syntax for READ statement is as follows:

READ TABLE itab


{FROM wa|WITH TABLE KEY comp1=dobj1 … compn=dobjn}|
{WITH KEY comp1=dobj1 … compn=dobjn [BINARY SEARCH]}|
{INDEX idx}
INTO
{wa[COMPARING comp1 … compn|TRANSPORTING comp1 …
compn]|ASSIGNING <fs> [CASTING]|REFERENCE INTO dref}|
{TRANSPORTING NO FIELDS}.

The values of the search key can be specified either implicitly in a work area wa after
FROM, or by explicitly listing the components of the table key after TABLE KEY. The
work area wa must be a data object that is compatible with the line type of the internal
table. The dobj data object in TABLE KEY must be compatible with the line type of the
internal table. Here the standard table is searched using linear search, sorted table is
searched using binary search and hashed tables are searched based on hash algorithm.

If we don’t use the TABLE addition before KEY, we can use any component comp of the
internal table as search keys (free key). If the addition BINARY SEARCH is specified, the
search is binary instead of linear for standard table. It can be specified for sorted tables,

153
but has no effect on sorted tables. The addition BINARY SEARCH is not permitted for
hashed tables.

In standard tables and sorted tables, the table index of the row to be read can be specified
explicitly in idx. For idx, a data object of type i is expected. If the value of idx is
smaller than or equal to 0, or greater than the number of rows in the table, no line is read
and sy-subrc is set to 4.

The content of the found line is assigned to the work area wa. The addition COMPARING
compares the specified components comp1 … compn in a found line before they are
transported with the corresponding components of the work area. If the addition
TRANSPORTING is specified, only the specified components comp1 … compn in the
found line are assigned to the corresponding components of the work area. COMPARING
must be specified before TRANSPORTING.

When the addition TRANSPORTING NO FIELDS is used, the statement READ TABLE
only checks whether the line that is being searched for exists, and fills the system field
sy-subrc and sy-tabix. The system can then no longer access the content of the
found fields.

The program below fills a sorted table with a list of square numbers. The READ statement
reads the line of the table in which the key field col1 has the same value as in the work
area and copies it into the work area. Only the contents of col2 are copied into the work
area LINE. SY-SUBRC is zero, and SY-TABIX is 3, because itab is an index table.

REPORT z_itb_read01.

CLASS example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS.

CLASS example IMPLEMENTATION.


METHOD main.

DATA: BEGIN OF line,


col1 TYPE i,
col2 TYPE i,
END OF line.

DATA itab LIKE SORTED TABLE OF line


WITH UNIQUE KEY col1.

DO 4 TIMES.
line-col1 = sy-index.
line-col2 = sy-index ** 2.
INSERT line INTO TABLE itab.
ENDDO.

"sets the line components to initail values

154
CLEAR line.

WRITE: ' line-col1', ' line-col2'.


WRITE /'---------------------------'.
LOOP AT itab INTO line.
WRITE: / line-col1, line-col2.
ENDLOOP.

SKIP.

CLEAR line.

READ TABLE itab WITH TABLE KEY col1 = 3


INTO line TRANSPORTING col2.

WRITE 'Value read with key = 3'.

SKIP.

WRITE: ' line-col1', ' line-col2'.


WRITE /'---------------------------'.
WRITE: / line-col1, line-col2.

ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
example=>main( ).

The above program produces the following output.

The example below reads the first ten lines of the internal table sflight_tab using
the index.

REPORT z_itb_read02.

CLASS example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.

155
ENDCLASS.

CLASS example IMPLEMENTATION.


METHOD main.
"sflight is a flight details table in
"abap dictionary
DATA sflight_tab TYPE SORTED TABLE OF sflight
WITH NON-UNIQUE KEY seatsocc.
"declare line work area, that will hold
"one row at a time
DATA sflight_wa LIKE LINE OF sflight_tab.

SELECT * FROM sflight


INTO TABLE sflight_tab
WHERE carrid = 'LH' AND connid = '400'.

WRITE: 'AirlineID', ' Con No',


' Flight Date', ' Type',
' Currency',' Fare'.
WRITE: / '---------------------------------------------------------
-----------------------'.

DO 10 TIMES.

READ TABLE sflight_tab INDEX sy-index INTO sflight_wa.

IF sy-subrc <> 0.
EXIT.
ELSE.
WRITE: / sflight_wa-carrid, ' ',
sflight_wa-connid, ' ',
sflight_wa-fldate, ' ',
sflight_wa-planetype, ' ',
sflight_wa-currency,
sflight_wa-price.
ENDIF.

ENDDO.

ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
example=>main( ).

Following is the output.

156
In the third example the READ statement uses a WHILE loop to read all lines of the table
sflight_tab one after the other using the table index in the work area sflight_wa.
Using the COMPARING addition, all flights are selected in which no seats have yet been
booked.

REPORT z_itb_read03.

CLASS example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS.

CLASS example IMPLEMENTATION.


METHOD main.

DATA sflight_tab TYPE SORTED TABLE OF sflight


WITH UNIQUE KEY carrid connid fldate.
DATA sflight_wa LIKE LINE OF sflight_tab.
DATA subrc TYPE sy-subrc.

SELECT * FROM sflight


INTO TABLE sflight_tab
WHERE carrid = 'LH'.

subrc = sy-subrc.

WRITE: 'AirlineID', ' Con No',


' Flight Date', ' Occupied Seats'.
WRITE: / '-------------------------------------------------------'.

WHILE subrc = 0.

sflight_wa-seatsocc = 0.

157
READ TABLE sflight_tab INDEX sy-index INTO sflight_wa
COMPARING seatsocc
TRANSPORTING carrid
connid
fldate
seatsocc.

CASE sy-subrc.
WHEN 0.
"COLOR addition change the background color of
"output of the current WRITE statement
WRITE: / sflight_wa-carrid, ' ',
sflight_wa-connid, ' ',
sflight_wa-fldate, ' ',
sflight_wa-seatsocc COLOR = 6.

subrc = sy-subrc.

WHEN 2.
WRITE: / sflight_wa-carrid, ' ',
sflight_wa-connid, ' ',
sflight_wa-fldate, ' ',
sflight_wa-seatsocc COLOR = 5.
subrc = 0.

WHEN 4 OR 8.
EXIT.
ENDCASE.

ENDWHILE.
ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
example=>main( ).

Following is the screen shot of the output.

158
The program below fills a hashed table with a list of square numbers. The READ
statement reads the line of the table in which the key field col1 has the value 2 and
assigns it to the field symbol <FS>. The program then assigns the value 100 to
component col2 of <FS>. This also changes the corresponding table field.

REPORT z_itb_read04.

CLASS example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS.

CLASS example IMPLEMENTATION.


METHOD main.

159
DATA: BEGIN OF line,
col1 TYPE i,
col2 TYPE i,
END OF line.

DATA itab LIKE HASHED TABLE OF line


WITH UNIQUE KEY col1.

FIELD-SYMBOLS <fs> LIKE LINE OF itab.

DO 4 TIMES.
line-col1 = sy-index.
line-col2 = sy-index ** 2.
INSERT line INTO TABLE itab.
ENDDO.

WRITE: ' line-col1', ' line-col2'.


WRITE /'------------------------'.
LOOP AT itab INTO line.
WRITE: / line-col1, line-col2.
ENDLOOP.

READ TABLE itab WITH TABLE KEY col1 = 2 ASSIGNING <fs>.


<fs>-col2 = 100.

SKIP.

LOOP AT itab INTO line.


IF line-col2 = 100.
WRITE: / line-col1 COLOR 5, line-col2 COLOR 5.
ELSE.
WRITE: / line-col1, line-col2.
ENDIF.
ENDLOOP.

ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
example=>main( ).

Following is the output of the above example.

160
The following program checks whether a particular line exists in the internal table
sflight_carr, and assign the table index of the found line in sy-tabix to idx.

REPORT z_itb_read05.

"Parameters are components of a selection screen that


"are assigned a global elementary data object in program
"and an input field on the selection screen. A special
"screen that can be defined without the use of the Screen
"Painter by using the statement like PARAMETERS
PARAMETERS p_carrid TYPE scarr-carrid.

CLASS example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS.

CLASS example IMPLEMENTATION.


METHOD main.

DATA scarr_tab TYPE SORTED TABLE OF scarr


WITH UNIQUE KEY carrid.
DATA idx TYPE i.

"scarr table stores airline details


SELECT * FROM scarr INTO TABLE scarr_tab.

READ TABLE scarr_tab WITH TABLE KEY carrid = p_carrid


TRANSPORTING NO FIELDS.

IF sy-subrc = 0.
idx = sy-tabix.
ENDIF.

WRITE: 'Value find at ', idx.

ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
example=>main( ).

Following is produce after execution.

161
Use of LOOP AT Loop

The LOOP AT loop can be used to read rows from internal table sequentially. The row
that has been read is available in the statement block of the loop. The sequence in which
the table lines are read depends on the table category. Standard tables and sorted tables
are read based on their ascending table index. The lines of hashed tables are read either in
the sequence in which they were inserted into the table or in the sort sequence if they
were sorted with the SORT statement.

In index tables sy-tabix is filled with the index of the current line in each loop pass.
Once the loop has been completely processed, sy-tabix is assigned that value that it
had prior to entering the loop.

We insert lines behind the current line; these new lines will be processed in the processed
in the subsequent loop passes. An endless loop can result. If we delete a line after the
current line, it will not be processed in a subsequent loop pass. If we insert lines in front
of the current line, the internal loop counter is increased by one with each inserted line. If
we delete a line before or at the current line, the internal loop counter will be decreased
accordingly. The sy-tabix is affected in the subsequent loop pass. Note, statements
such as CLEAR, FREE, REFRESH and SORT and all types of assignments to internal
table are not allowed in classes.

Control level processing is allowed within a LOOP AT over an internal table. This means
that you can divide sequences of entries into groups based on the contents of certain
fields. Internal tables are divided into groups according to the sequence of the fields in
the line structure. The first column defines the highest control level and so on. The
control level hierarchy must be known when you create the internal table.

The control levels are formed by sorting the internal table in the sequence of its structure,
that is, by the first field first, then by the second field, and so on. Tables in which the
table key occurs at the start of the table are particularly suitable for control level
processing.

The statements AT and ENDAT define statement blocks that are executed at control
breaks. Control break is the change from one control level to another in the control level
processing. The additions AT statements determine the control break at which their
statement blocks are executed. Within these statement blocks, the statement SUM can be
specified to add together the numeric components of the control level. Statements in the
LOOP-ENDLOOP control structure that are not executed within an AT-ENDAT control
structure are executed in each pass of the loop.

LOOP AT itab INTO {wa|ASSIGNING|REFERENCE INTO dref|


TRANSPORTING NO FIELDS}.

AT FIRST. ...... ENDAT.

162
AT NEW comp1. ...... ENDAT.
AT NEW comp2. ...... ENDAT.
........................

<single_line processing>

........................
AT END OF comp2. ...... ENDAT.
AT END OF comp1. ......ENDAT.
AT LAST. ...... ENDAT.

ENDLOOP.

The innermost hierarchy level <single line processing> processes the table lines that
do not correspond to a control level change. You do not have to use all control level
statements. But you must place the used ones in the above sequence. You should not use
control level statements in loops where the line selection is restricted by WHERE or FROM
and TO. Neither should the table be modified during the loop.

FIRST is used to define the control level by the first line of the internal table. The
control break takes place when this line is read. NEW defines the control levels by the
beginning of a group of lines with the same content in the content compi and in the
components to the left of compi. END OF defines the control levels by the end of a
group of lines with the same content in the content compi and in the components to the
left of compi. In both NEW and END OF the control breaks take place when the content
of the component compi or another component to the left of compi changes. If a
control level field compi is not known until runtime, you can specify it dynamically as
(compi). LAST is used to define the control level by the last line of the internal table.
The control break takes place when the last line is read.

Note: After LOOP, a restricting condition can only be specified if this selects a
consecutive line block of the internal table. Otherwise, the behavior of control level
processing is undefined.

If a work area does not contain the current line in the AT ... ENDAT statement block.
All character fields to the right of the current group key are filled with asterisks (*). All
other fields to the right of the current group key contain their initial value.

In the program below in the LOOP - ENDLOOP block, the work area LINE is output for
each loop pass. The first field of the table key, col1, is used for control level processing.
The total for all numeric fields is always calculated when the contents of col1 change
and when the system is in the last loop pass.

REPORT z_itb_loop.

CLASS example DEFINITION.


PUBLIC SECTION.

163
CLASS-METHODS main.
ENDCLASS.

CLASS example IMPLEMENTATION.


METHOD main.

DATA: BEGIN OF line,


col1 TYPE c LENGTH 1,
col2 TYPE i,
col3 TYPE i,
END OF line.

DATA itab LIKE HASHED TABLE OF line


WITH UNIQUE KEY col1 col2.

line-col1 = 'A'.
DO 3 TIMES.
line-col2 = sy-index.
line-col3 = sy-index * 2.
INSERT line INTO TABLE itab.
ENDDO.

line-col1 = 'B'.
DO 3 TIMES.
line-col2 = sy-index.
line-col3 = sy-index * 4.
INSERT line INTO TABLE itab.
ENDDO.

SORT itab BY col1 ASCENDING.

WRITE: 'COL1', ' COL2', ' COL3'.


"print horizontal line
ULINE.

LOOP AT itab INTO line.


WRITE: / line-col1, line-col2, line-col3.

"Control breaks when the contents (A, B)


"of col1 change
AT END OF col1.
"sum up all numeric fields individually
"for A and B
SUM.
ULINE.
WRITE: / line-col1 COLOR 6, line-col2 COLOR 6,
line-col3 COLOR 6.
ULINE.
SKIP 2.
ENDAT.

"control breaks when last line is reached


AT LAST.
"sum up all numeric fields
SUM.
ULINE.

164
WRITE: / line-col1 COLOR 6, line-col2 COLOR 6,
line-col3 COLOR 6.
ULINE.
ENDAT.

ENDLOOP.
ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
example=>main( ).

Following is the output of the above program.

In this example, the sorted internal table itab is filled with data from the database table
sbook using the Open SQL statement SELECT. The sequence of the columns in the
internal table defines the control level hierarchy. Since the table key is the entire line, the
sort sequence and the control level hierarchy are the same. The sequence of the AT-
ENDAT blocks within the LOOP and ENDLOOP statements is important.

REPORT z_itb_loop02.

CLASS example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS.

CLASS example IMPLEMENTATION.


METHOD main.

"sbook is the flight booking table

165
DATA: BEGIN OF line,
carrid TYPE sbook-carrid,
connid TYPE sbook-connid,
fldate TYPE sbook-fldate,
custtype TYPE sbook-custtype,
class TYPE sbook-class,
bookid TYPE sbook-bookid,
END OF line.

DATA itab LIKE SORTED TABLE OF line


WITH UNIQUE KEY table_line.

SELECT carrid connid fldate


custtype class bookid FROM sbook
INTO CORRESPONDING FIELDS OF TABLE itab
WHERE custtype = 'B'.

LOOP AT itab INTO line.

"control breaks when 1st line is read


AT FIRST.
WRITE / 'List of Bookings'.
WRITE / '----------------'.
ENDAT.

"control breaks when the contents of the


"component carrid or another component to
"the left of carrid changes.
AT NEW carrid.
WRITE: / 'Airline Code:', line-carrid.
ENDAT.

AT NEW connid.
WRITE: / 'Flight Conn ID:', line-connid.
ENDAT.

AT NEW fldate.
WRITE: / 'Flight Date:', line-fldate.
ENDAT.

AT NEW custtype.
WRITE: / 'Customer Type:', line-custtype.
ENDAT.

WRITE: / 'Booking ID:', line-bookid,


'Flight Class:', line-class.

"control breaks when the contents of


"component class changes
AT END OF class.
ULINE.
ENDAT.

ENDLOOP.
ENDMETHOD.
ENDCLASS.

166
START-OF-SELECTION.
example=>main( ).

Following is the output of the above example.

Modifying Rows

To change the contents of a single line or several lines we can us the following statement:

MODIFY {TABLE itab|itab INDEX idx FROM wa


[TRANSPORTING comp1 comp2 ...]
ASSIGNING <fs> [CASTING]|REFERENCE INTO dref}|
{itab FROM wa
TRANSPORTING comp1 comp2 ... WHERE log_exp}.

The system searches for the relevant lines as follows: In standard table linear search is
used, in sorted table binary search is applied, while in hashed table the entry is found
using the hash algorithm of the internal table. The work area <wa>, which must be
compatible with the line type of the internal table, plays a double role in this statement.
Not only it is used to find the line that you want to change, but it also contains the new
contents. The system searches the internal table for the line whose table key corresponds
to the key fields in <wa>. The following example uses the TABLE addition.

167
REPORT z_itb_modify01.

CLASS example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS.

CLASS example IMPLEMENTATION.


METHOD main.

DATA scarr_tab TYPE SORTED TABLE OF scarr


WITH UNIQUE KEY carrid.

DATA: scarr_wa TYPE scarr,


airline_code TYPE c LENGTH 3.

SELECT * FROM scarr


INTO TABLE scarr_tab.

airline_code = 'AA'.

READ TABLE scarr_tab INTO scarr_wa


WITH TABLE KEY carrid = airline_code.

WRITE: 'Airline ID ', ' Name',


' Currency'.
ULINE.
WRITE / 'BEFORE MODIFICATION.'.
WRITE / '------------------'.
WRITE: / scarr_wa-carrid,
' ', scarr_wa-carrname,
scarr_wa-currcode.

SKIP.
WRITE 'AFTER MODIFICATION.'.
WRITE / '------------------'.

"change the contents of an internal table


"based on the values in workarea and the
"currcode field is only assigned to the
"corresponding component of the work area
scarr_wa-currcode = 'EUR'.
MODIFY TABLE scarr_tab FROM scarr_wa
TRANSPORTING currcode.

"read again that specific line


READ TABLE scarr_tab INTO scarr_wa
WITH TABLE KEY carrid = airline_code.

WRITE: / scarr_wa-carrid,
' ', scarr_wa-carrname,
scarr_wa-currcode.

ENDMETHOD.
ENDCLASS.

168
START-OF-SELECTION.
example=>main( ).

The following example changes the currency to EURO using the index access.

REPORT z_itb_modify02.

CLASS example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS.

CLASS example IMPLEMENTATION.


METHOD main.

DATA scarr_tab TYPE SORTED TABLE OF scarr


WITH UNIQUE KEY carrid.

DATA: scarr_wa TYPE scarr,


idx TYPE sy-tabix,
airline_code TYPE c LENGTH 3.

SELECT * FROM scarr


INTO TABLE scarr_tab.

airline_code = 'AA'.

READ TABLE scarr_tab INTO scarr_wa


WITH TABLE KEY carrid = airline_code.

WRITE: 'Airline ID ', ' Name',


' Currency'.
ULINE.
WRITE / 'BEFORE MODIFICATION.'.
WRITE / '------------------'.
WRITE: / scarr_wa-carrid,
' ', scarr_wa-carrname,
scarr_wa-currcode.

SKIP.
WRITE 'AFTER MODIFICATION.'.
WRITE / '------------------'.

idx = sy-tabix.
scarr_wa-currcode = 'EUR'.
MODIFY scarr_tab INDEX idx FROM scarr_wa
TRANSPORTING currcode.

READ TABLE scarr_tab INTO scarr_wa


WITH TABLE KEY carrid = airline_code.

WRITE: / scarr_wa-carrid,
' ', scarr_wa-carrname,
scarr_wa-currcode.

169
ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
example=>main( ).

Following is the output of the above two examples.

Deleting Rows

To delete a line(s) of an internal table we can use the DELETE statement. The syntax
follows as:

DELETE {{TABLE itab FROM wa|WITH TABLE KEY comp1=dobj1 …


compn=dobjn}|itab [INDEX idx]}}|
{itab [FROM idx1] [TO idx2] [WHERE log_exp]}|
{ADJACENT DUPLICATES FROM itab [COMPARING
comp1 …|ALL FIELDS]}.

With variant TABLE we have to specify the line by using the table key. In standard and
sorted table we can specify the line to be deleted by its table index idx. idx expects a
data object of the type i. Within a LOOP, we can omit the INDEX addition. In this case,
the current table line of the LOOP-pass is deleted.

To delete several lines at once, we have to specify at least one of the additions FROM, TO,
or WHERE. If we specify FROM, all the table rows from the table index idx1 onwards are
included. When addition TO is added only the table rows up to table index idx2 are
included. If idx2 is less than idx1, no rows are deleted. We can specify any logical
expression log_exp after WHERE, for which the first operand of each individual
comparison is a component of the internal table.

With additions ADJACENT DUPLICATES, the statement DELETE deletes all lines in
certain groups of lines, except for the first line of the group. These are groups of lines that
follow one another and have the same content in certain components. If the addition
COMPARING is not specified, the groups are determined by the content of the key fields.
If the addition COMPARING is specified, the groups are determined either by the content

170
of the specified components comp1 comp2 ... or the content of all components ALL
FIELDS.

The following program fills the hashed table with data. The DELETE statement deletes
the line where the key field column id has the contents of 307.

REPORT z_itb_delete01.

CLASS example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS.

CLASS example IMPLEMENTATION.


METHOD main.

DATA: BEGIN OF line,


id TYPE i,
name TYPE c LENGTH 20,
END OF line.

DATA itab LIKE HASHED TABLE OF line


WITH UNIQUE KEY id.

line-id = 100. line-name = 'Asghar'.


INSERT line INTO TABLE itab.

line-id = 200. line-name = 'Safdar'.


INSERT line INTO TABLE itab.

line-id = 305. line-name = 'Zeeshan'.


INSERT line INTO TABLE itab.

line-id = 307. line-name = 'Safdar'.


INSERT line INTO TABLE itab.

WRITE: ' ID', ' Name'.


ULINE.
WRITE 'Before Delete'.
WRITE / '-------------'.
LOOP AT itab INTO line.
WRITE: / line-id, line-name.
ENDLOOP.

DELETE TABLE itab WITH TABLE KEY id = 307.

SKIP.
WRITE / 'After Delete'.
WRITE / '------------'.
LOOP AT itab INTO LINE.
WRITE: / LINE-ID, LINE-name.
ENDLOOP.

ENDMETHOD.
ENDCLASS.

171
START-OF-SELECTION.
example=>main( ).

Following is the output of above program.

The next program fills a hashed table with a list of square numbers. The DELETE
statement deletes the lines of the table where the content of field col2 is greater than 1
and the content of field col1 is less than 4.

REPORT z_itb_delete02.

CLASS example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS.

CLASS example IMPLEMENTATION.


METHOD main.

DATA: BEGIN OF line,


col1 TYPE i,
col2 TYPE i,
END OF line.

DATA itab LIKE HASHED TABLE OF line


WITH UNIQUE KEY col1.

DO 4 TIMES.
line-col1 = sy-index.
line-col2 = sy-index ** 2.
INSERT line INTO TABLE itab.
ENDDO.

WRITE: ' No.',


' Square'.
ULINE.

172
WRITE 'Before Delete'.
WRITE / '-------------'.
LOOP AT itab INTO line.
WRITE: / line-col1, line-col2.
ENDLOOP.

DELETE itab WHERE ( col2 > 1 ) AND ( col1 < 4 ).

WRITE / 'After Delete'.


WRITE / '-------------'.
LOOP AT itab INTO line.
WRITE: / line-col1, line-col2.
ENDLOOP.

ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
example=>main( ).

The above program produces the following output.

The example below creates and fills a standard table. Here, the first DELETE statement
deletes the second line from itab because the second line has the same contents as the
first line. The second DELETE statement deletes the second line from the remaining table
because the contents of the field col1 is the same as in the first line. The third DELETE
statement deletes the third and fourth line from the remaining table because the contents
of the default key field col2 are the same as on the second line. Although the contents of
the default key are the same for the first and the fifth line, the fifth line is not deleted
because it is not adjacent to the first line.

REPORT z_itb_delete03.

CLASS example DEFINITION.

"static methods
PUBLIC SECTION.
CLASS-METHODS: main,

173
make_list.

"static attributes
PRIVATE SECTION.
CLASS-DATA: BEGIN OF line,
col1 TYPE i,
col2 TYPE c,
END OF line.

CLASS-DATA pos TYPE i.


CLASS-DATA itab LIKE STANDARD TABLE OF line
WITH NON-UNIQUE KEY col2.

ENDCLASS.

CLASS example IMPLEMENTATION.

METHOD make_list.

SKIP TO LINE 1.
LOOP AT itab INTO line.
"AT position the output according to pos
WRITE: AT /pos line-col1, line-col2.
ENDLOOP.

ENDMETHOD.

METHOD main.

line-col1 = 1. line-col2 = 'A'. APPEND line TO itab.


line-col1 = 1. line-col2 = 'A'. APPEND line TO itab.
line-col1 = 1. line-col2 = 'B'. APPEND line TO itab.
line-col1 = 2. line-col2 = 'B'. APPEND line TO itab.
line-col1 = 3. line-col2 = 'B'. APPEND line TO itab.
line-col1 = 4. line-col2 = 'B'. APPEND line TO itab.
line-col1 = 5. line-col2 = 'A'. APPEND line TO itab.

pos = 0.

CALL METHOD make_list.

DELETE ADJACENT DUPLICATES FROM itab COMPARING ALL FIELDS.


pos = 15.
CALL METHOD make_list.

DELETE ADJACENT DUPLICATES FROM itab COMPARING col1.


pos = 30.
CALL METHOD make_list.

DELETE ADJACENT DUPLICATES FROM itab.


pos = 45.
CALL METHOD make_list.

ENDMETHOD.
ENDCLASS.

174
START-OF-SELECTION.
example=>main( ).

Following is the output of above coding.

Processing Entire Internal Tables

When we access the entire internal table, we address the body of the table as a single data
object. The following operations on the body of an internal table are relevant:

Initialization

We can initialize internal tables with the CLEAR, REFRESH and FREE statements.

The CLEAR statement deletes all the rows and all the memory required, except the initial
memory requirement is released.

CLEAR itab.

For table with header line we must place two brackets ([ ]) after the table name as:

CLEAR itab[].

The REFRESH statement sets an internal table to its initial value, meaning that it deletes
all rows of the internal table. The memory space required for the table is freed up to the
initial memory size INITIAL SIZE. If the internal table has no header line, REFRESH
acts like CLEAR. Therefore, you should always use CLEAR instead of REFRESH.

REFRESH itab.

FREE has the same effect as the REFRESH statement, though the entire memory area
occupied by the table rows is released, and the initial memory area remains unoccupied.

FREE itab.

In the program, an internal table itab is filled and then initialized with REFRESH. The
IF statement uses the expression itab IS INITIAL to find out whether itab is
empty. If so, the memory is released.

175
REPORT z_itb_init01.

CLASS example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS.

CLASS example IMPLEMENTATION.


METHOD main.

DATA: BEGIN OF line,


col1,
col2,
END OF line.

DATA itab LIKE TABLE OF line.

line-col1 = 'A'.
line-col2 = 'B'.
APPEND line TO itab.

REFRESH itab.

IF itab IS INITIAL.
WRITE 'ITAB is empty'.
FREE itab.
ENDIF.

ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
example=>main( ).

Following is the output.

Assignment

Like other data objects, we can use internal tables as operands in a MOVE statement.

MOVE itab1 TO itab2.

Or the equivalent statement.

itab2 = itab1.

176
Both operands must either be compatible or convertible. These statements assign the
entire contents of table itab1 to table itab2, including the data in any nested internal
tables. The original contents of the target table are overwritten. When using internal
tables with header lines, the header line and the body of the table have the same name. If
we want to address the body of the table in an assignment, we must place two brackets ([
]) after the table name. But it must be noted that tables with header line is not supported
in OO context.

The example creates two standard tables itab1 and itab2 with the line type of the
structure line. itab1 has a header line. After filling itab1 line by line using the
APPEND statement, its entire contents are assigned to itab2. Note the brackets in the
statement.

REPORT z_itb_asgn01.

START-OF-SELECTION.

DATA: BEGIN OF line,


col1(1) TYPE c,
col2(1) TYPE c,
END OF line.

DATA: itab1 LIKE TABLE OF line WITH HEADER LINE,


itab2 LIKE TABLE OF line.

line-col1 = 'A'.
line-col2 = 'B'.

APPEND line TO itab1.

itab2 = itab1[].

WRITe: 'Col1', ' Col2'.


ULINE.

LOOP AT itab2 INTO line.


WRITE: / line-col1,
' ',
line-col2.
ENDLOOP.

Following is the output of the above code.

177
In the following example ftab is a sorted table with line type f and a non-unique key.
itab is a hashed table with line type i and a unique key. The line types, and therefore
the entire tables, are convertible. It is therefore possible to assign the contents of itab to
ftab. When you assign the unsorted table itab to the sorted table ftab, the contents
are automatically sorted by the key of ftab.

REPORT z_itb_asgn02.

CLASS example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS.

CLASS example IMPLEMENTATION.


METHOD main.

DATA: ftab TYPE SORTED TABLE OF f


WITH NON-UNIQUE KEY table_line,
itab TYPE HASHED TABLE OF i
WITH UNIQUE KEY table_line,
fl TYPE f.

DO 3 TIMES.
INSERT sy-index INTO TABLE itab.
ENDDO.

WRITE: 'Contents of itab'.


LOOP AT itab INTO fl.
WRITE: / fl.
ENDLOOP.

ftab = itab.

SKIP.
WRITE: / 'Contents of ftab after Assignment'.
LOOP AT ftab INTO fl.
WRITE: / fl.
ENDLOOP.

ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
example=>main( ).

Following is the output.

178
Comparison

We can use internal tables as operands in logical expressions as:

itab1 <operator> itab2.

The <operator> can be any relational operator (EQ, =, <>, NE, <, LT, <=,
LE, >, GT, >=, GE). For table with header line we must place two brackets ([ ])
after the table name.

If two internal tables contain the same number of lines, they are compared line by line,
component by component. If components of the table lines are themselves internal tables,
they are compared recursively. If you are testing internal tables for anything other than
equality, the comparison stops when it reaches the first pair of components that are
unequal, and returns the corresponding result.

This example creates two standard tables, itab and jtab. itab is filled with 3 lines
and copied to jtab. Then, another line is appended to itab and the first logical
expression tests whether itab is greater than jtab. After appending the same line to
jtab, the second logical expression tests whether both tables are equal. Then, another
line is appended to itab and the third logical expressions tests whether jtab is less
than or equal to itab. Next, another line is appended to jtab. Its contents are unequal
to the contents of the last line of itab. The next logical expressions test whether itab
is not equal to jtab. The first table field whose contents are different in itab and
jtab is col1 in the last line of the table: 30 in itab and 50 in jtab. Therefore, in the
last logical expression, itab is less than jtab.

REPORT z_itb_compar01.

CLASS example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS.

CLASS example IMPLEMENTATION.


METHOD main.

DATA: BEGIN OF line,

179
col1 TYPE i,
col2 TYPE i,
END OF line.

DATA: itab LIKE TABLE OF line,


jtab LIKE TABLE OF line.

DO 3 TIMES.
line-col1 = sy-index.
line-col2 = sy-index ** 2.
APPEND line TO itab.
ENDDO.

jtab = itab.

line-col1 = 10. line-col2 = 20.


APPEND line TO itab.

IF itab > jtab.


WRITE / 'itab is greater than jtab'.
ENDIF.

APPEND line TO jtab.

IF itab = jtab.
WRITE / 'itab is equal to jtab'.
ENDIF.

line-col1 = 30. line-col2 = 80.


APPEND line TO itab.

IF jtab <= itab.


WRITE / 'jtab is less than or equal to itab'.
ENDIF.

line-col1 = 50. line-col2 = 60.


APPEND line TO jtab.

IF itab <> jtab.


WRITE / 'itab is not equal to jtab'.
ENDIF.

IF itab < jtab.


WRITE / 'itab is less than jtab'.
ENDIF.

ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
example=>main( ).

Following is the output of the above code.

180
Sorting

The standard and hashed tables can be sorted by using the SORT statement. Using SORT
for sorted tables is syntactically prohibited. Following is the syntax of SORT statement.

SORT itab [STABLE]


{ { [ASCENDING|DESCENDING]
[AS TEXT]
[BY {comp1 [ASCENDING|DESCENDING] [AS TEXT]}
{comp2 [ASCENDING|DESCENDING] [AS TEXT]}
... ] }.

STABLE is used to perform stable sorting, which means that the relative sequence of
lines that does not change in the sort key remains unchanged in the sort.

The addition ASCENDING or DESCENDING can be used to specify the sort direction
explicitly as ascending or descending. If neither of the additions is entered, the table is
sorted in ascending order.

The addition AS TEXT specified that text-type components are sorted according to the
locale (defines language-dependent and country-dependent characteristics of characters,
such as the sort sequence or uppercase/lowercase conversion) of the current text
environment (part of the runtime environment of an ABAP program and is made up of a
language, a locale and a system codepage.). If AS TEXT is not specified, text-type
components are sorted according to the encoding in the code page of the current text
environment.

With the addition BY compi, the table is not sorted according to the table key, but
instead according to the components comp1 comp2... that are specified after it.

The program below demonstrates sorting.

REPORT z_itb_sort01.

CLASS example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS: main,
make_list.

PRIVATE SECTION.
CLASS-DATA: BEGIN OF line,

181
land TYPE c LENGTH 3,
name TYPE c LENGTH 10,
age TYPE i,
weight TYPE p DECIMALS 2,
END OF line.

CLASS-DATA itab LIKE STANDARD TABLE OF line


WITH NON-UNIQUE KEY land.
ENDCLASS.

CLASS example IMPLEMENTATION.

METHOD make_list.

LOOP AT itab INTO line.


WRITE: / line-land COLOR 7,
line-name COLOR 7,
line-age COLOR 7,
line-weight COLOR 7.
ENDLOOP.
SKIP.

ENDMETHOD.

METHOD main.

line-land = 'G'. line-name = 'Hans'.


line-age = 20. line-weight = '80.00'.
APPEND line TO itab.

line-land = 'USA'. line-name = 'Howard'.


line-age = 40. line-weight = '95.00'.
APPEND line TO itab.

line-land = 'GB'. line-name = 'Jenny'.


line-age = 18. line-weight = '50.00'.
APPEND line TO itab.

line-land = 'F'. line-name = 'Michele'.


line-age = 30. line-weight = '60.00'.
APPEND line TO itab.

line-land = 'G'. line-name = 'Karl'.


line-age = 60. line-weight = '75.00'.
APPEND line TO itab.

WRITE: 'Land' COLOR 5, 'Name' COLOR 5,


' Age' COLOR 5,
' Weight' COLOR 5.
ULINE.

WRITE / 'Without sorting' COLOR 6.


CALL METHOD make_list.

WRITE 'With sorting' COLOR 6.


SORT itab.

182
CALL METHOD make_list.

WRITE 'Stable sorting' COLOR 6.


SORT itab STABLE.
CALL METHOD make_list.

WRITE 'Sorting by land and weight' COLOR 6.


SORT itab DESCENDING BY land weight ASCENDING.
CALL METHOD make_list.

ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
example=>main( ).

Following is the output of the above example.

In the following example the table is sorted three times. First, it is sorted binarily by the
TEXT field. Second, it is sorted binarily by the XTEXT field. Third, it is sorted
alphabetically by the TEXT field. Since there is no directly corresponding case in
English, we have taken the results from a German text environment.

183
REPORT z_itb_sort02.

CLASS example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS: main,
make_list.

PRIVATE SECTION.
CLASS-DATA: BEGIN OF line,
text TYPE c LENGTH 6,
xtext TYPE x LENGTH 160,
END OF line.

CLASS-DATA itab LIKE HASHED TABLE OF line


WITH UNIQUE KEY text.

ENDCLASS.

CLASS example IMPLEMENTATION.


METHOD make_list.

LOOP AT itab INTO line.


WRITE / line-text COLOR 7.
ENDLOOP.
SKIP.

ENDMETHOD.

METHOD main.

line-text = 'Umer'.
"convertes a text to a sortable byte sequence and the
"result is assigned to xtext
CONVERT TEXT line-text INTO SORTABLE CODE line-xtext.
INSERT line INTO TABLE itab.

line-text = 'Ömer'.
CONVERT TEXT line-text INTO SORTABLE CODE line-xtext.
INSERT line INTO TABLE itab.

line-text = 'Omer'.
CONVERT TEXT line-text INTO SORTABLE CODE line-xtext.
INSERT line INTO TABLE itab.

line-text = 'Imer'.
CONVERT TEXT line-text INTO SORTABLE CODE line-xtext.
INSERT line INTO TABLE itab.

WRITE / 'Sorted binarily by text field' COLOR 6.


SORT itab.
CALL METHOD make_list.

WRITE / 'Sorted binarily by xtext field' COLOR 6.


SORT itab BY xtext.
CALL METHOD make_list.

184
WRITE / 'Sorted alphabetically by text field' COLOR 6.
SORT itab AS TEXT.
CALL METHOD make_list.

ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
example=>main( ).

Following is the output.

185
Classes and Objects
Object Oriented Programming is based on the encapsulation of data and its associated
functionality in classes. Classes in turn are used to create instance (objects). ABAP
Objects represents the part of the ABAP programming language that allows for OOP on
the basis of classes. The ABAP Objects streamlined the existing ABAP syntax using the
concept of syntax cleansing that is many outdated and obsolete language constructs are
forbidden in ABAP Objects, which are allowed outside of classes only for reasons of
compatibility.

A class is the pattern or template for an object much like a data type is the template for a
data object. Classes in ABAP Objects can be declared either globally or locally.

Global Classes

A global class is visible and can be used in every program of the same AS ABAP,
provided that no limitation by the package of the class exists. The global classes of an AS
ABAP form its class library. Global classes can only created in class pools program type
using the Class Builder tool (SE24) of the ABAP Workbench. We should define global
classes whenever we need objects of the same type in different programs. The global
class should be prefixed with cl_ .

Local Classes

A local class is only visible in the program in which it is defined. Local classes can be
defined in any ABAP program, except type groups and interface pools. We should use
local classes for objects that are only required in one program. Local class hides a global
class of the same name. The name of local class should be prefixed with lcl_.

Classes also behave like data types that are distinguished into global data types in the
ABAP Dictionary and local data types in any program.

Creating Classes
Both global and local classes are always declared in the declaration part of the program,
and they are implemented in its implementation part. For local classes we must enter the
relevant statements for the required program in the ABAP Editor, while for global classes
we must use the Class Builder (SE24) and fill the relevant input templates of the Class
Builder with data. The Class Builder then generates the corresponding statements in the
class pool of the class. The only code to enter for the global classes is the implementation
of the methods. The Class Builder hides the class pool behind user interface. However,
we can use the keyboard instead of the mouse, by selecting Goto…Section in Class
Builder which enables to edit the code of a global class in the ABAP Editor. The Class

186
Builder contains a small testing environment that can be used to test functionality of the
methods of a global class but for extensive tests, the ABAP Unit tool could be used.

Declaration and Implementation Part


In terms of syntax, each class definition always consists of a declaration part and an
implementation part. In declaration part we define various class components (Attributes,
Methods and Events). The implementation part contains the code for the class
components methods and events. The basic structure of a class is as follows:

CLASS myclass DEFINITION.


.........
ENDCLASS.

.................. .........

CLASS myclass IMPLEMENTATION.


.........
ENDCLASS.

With global classes, we usually wouldn’t see this structure directly. Once we have
created a global class, the Class Builder displays the empty class as shown below:

Following are the different components of a class.

Attributes

Attributes are internal data fields within a class that can have any ABAP data type. The
state of an object is determined by the contents of its attributes. In local classes instance
attributes are declared using the DATA statement, static attributes are declared with
CLASS-DATA and constant attributes are declared with CONSTANTS keyword. In global
classes, we can simply enter the attributes and their properties in the Attributes tab of
Class Builder. The constant in Class Builder can be created by specifying Constant in the
Level column of the Attributes tab and enter initial value in the Initial Column.

187
Methods

Methods are procedures in a class that define the behavior of an object. They can access
all of the attributes of a class. This allows them to change the data content of an object.
They also have a parameter interface, with which users can supply them with values
when calling them, and receive values back from them. The private attributes of a class
can only be changed by methods in the same class. Methods can be called by using the
CALL METHOD statement. Instance methods are declared using the METHODS keyword
while the static methods are declared with CLASS-METHODS. Methods are implemented
with keywords METHOD meth_name. … ENDMETHOHD.

In the Class Builder, we must enter the methods and their properties in the Methods tab.

Events

Objects or classes can use events to trigger event handler methods in other objects or
classes. In a normal method call, one method can be called by any number of users.
When an event is triggered, any number of event handler methods can be called. The link
between the trigger and the handler is not established until runtime. In a normal method
call, the calling program determines the methods that it wants to call. These methods
must exist. With events, the handler determines the events to which it wants to react.
There does not have to be a handler method registered for every event. The link between
trigger and handler is established dynamically in a program using the SET HANDLER
statement. The events of a class can be triggered in the methods of the same class using
the RAISE EVENT statement. Instance events are declared using the EVENTS keyword
while the static methods are declared with CLASS-EVENTS.

188
In global classes, events are declared on the Events tab of Class Builder.

Visibility Sections
Each component of the class must be assigned to one of the following three visibility
sections. The visibility sections define the visibility of the components of the class.

Public Section

All components of public section can be accessed by all external users, the methods of
subclasses and by the methods of the class. These components represent the interface
between the class and the external world.

Protected Section

All components of protected section can be accessed by the methods of the subclasses
and the methods of class. They represent the interface between the class and its
subclasses.

Private Section

Components in this section can only be used within the methods of the class. They are
not part of the interfaces of the class.

Following is the syntax used to separate the declaration part of class into three visibility
sections:

CLASS myclass DEFINITION.


PUBLIC SECTION
.........
PROTECTED SECTION
.........
PRIVATE SECTION
.........
ENDCLASS.

Following example demonstrate the basic structure of a local class.

REPORT z_oop_class01.

CLASS lcl_employee DEFINITION.

PUBLIC SECTION.
"Instance methods declared in public
"section visibilty
METHODS set_employee.

189
METHODS get_employee.

PRIVATE SECTION.
"Instance attributes declared in
"private section visibilty
DATA id TYPE c LENGTH 5.
DATA name TYPE string.
DATA address TYPE string.
DATA pay TYPE f.

ENDCLASS.

CLASS lcl_employee IMPLEMENTATION.

"Instance methods implementation


METHOD set_employee.
id = 'A001'.
name = 'Muhammad Asghar Khan'.
address = 'Peshawar, Pakistan'.
pay = '30000.0'.
ENDMETHOD.

METHOD get_employee.
WRITE 'Employee Details'.
SKIP.
WRITE: / 'ID: ', id.
WRITE: / 'Name: ', name.
WRITE: / 'Address: ', address.
WRITE: / 'Pay ', pay.
ENDMETHOD.

ENDCLASS.

CLASS lcl_demo DEFINITION.

PUBLIC SECTION.
"static method
CLASS-METHODS main.

ENDCLASS.

CLASS lcl_demo IMPLEMENTATION.

METHOD main.

"emp_obj is a reference variable which will be


"pointing to lcl_employee reference type
"or class
DATA emp_obj TYPE REF TO lcl_employee.
"instanitate employee object and assign the object
"reference to the refercne varibale emp_obj

190
CREATE OBJECT emp_obj.

"the instance component selector operator is used


"to call instance methods
emp_obj->set_employee( ).
emp_obj->get_employee( ).

ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
"the static component selector operator is used to
"call static method
lcl_demo=>main( ).

Following is the output of the above example.

In the class builder, we must select the assignment of a component to a visibility section
separately for each component in that we choose the option Public, Protected, or Private
for each component in the visibility column.

191
However, if we want to write programming code, we can select Goto Public Section,
Protected Section or Private Section to enter the complete declaration part of global class,
in the same way as that of a local class in the ABAP Editor.

Methods Revisited
We have already defined and called methods earlier, here we discuss the finer points of
methods in ABAP Objects.

Parameter Interfaces

The parameter interface of a method is defined by the additions to the METHOD and
CLASS-METHODS statements when the method is declared or by selection of Parameters
in the Class Builder. No further details of the parameter interface are required in the
implementation section between METHOD and ENDMETHOD. However, we can display
the interface during implementation of global classes.

The parameter interface of a method comprises formal parameters. Formal parameters are
local data objects that are declared in the method’s parameter interface rather then in the
body of the method. The actual parameters are used to initialize the formal parameters.
Actual parameters are placed in the parameter list of the method invocation. Within a
method, formal parameters can be used via their names in operand positions. The
following properties can be defined for a formal parameter:

• Parameter Type
• Kind of Parameter Passing
• Parameter Typing

192
• Supply Type of Parameter

We should note that methods in ABAP Objects can not be overloaded. In other words, we
can not use the same method names with different parameter interfaces, even when we
redefine methods in subclasses. We can define the following parameters:

Parameter Type

• Input Parameters: Input parameters are defined after the IMPORTING addition
to the METHODS or CLASS-METHODS statement, or are declared by selecting
Importing in the Type column on the Parameters tab page in the Class Builder.
The input parameters contain values that are passed into the method from the
calling program. These values originate outside of the method and they are
imported into it. When a method is called, the value of the assigned actual
parameter (parameter passed from calling statement) is assigned to the input
parameter. Input parameters for which pass by reference are defined can not be
overwritten in the method. Input parameters for which pass by value are defined
are not passed to the actual parameter when the procedure is exited.

The following example demonstrates the use of input parameters.

193
REPORT z_oop_methd01.

PARAMETERS: number1 TYPE i,


number2 TYPE i.

CLASS lcl_example DEFINITION.

PUBLIC SECTION.

METHODS add IMPORTING


no1 TYPE i
no2 TYPE i.
METHODS sub IMPORTING
no1 TYPE i
no2 TYPE i.
METHODS div IMPORTING
no1 TYPE i
no2 TYPE i.

CLASS-METHODS main.

ENDCLASS.

CLASS lcl_example IMPLEMENTATION.

METHOD add.
DATA sum TYPE i VALUE 0.
sum = no1 + no2.
WRITE: / 'Sum =', sum LEFT-JUSTIFIED.
ENDMETHOD.

METHOD sub.
DATA s TYPE i VALUE 0.
s = no2 + no1.
WRITE: / 'Subtraction =', s LEFT-JUSTIFIED.
ENDMETHOD.

METHOD div.
DATA d TYPE i VALUE 0.
d = no2 DIV no1.
WRITE: / 'Division =', d LEFT-JUSTIFIED.
ENDMETHOD.

METHOD main.

DATA obj TYPE REF TO lcl_example.

CREATE OBJECT obj.

obj->add( no1 = number1 no2 = number2 ).


obj->sub( no1 = number1 no2 = number2 ).

194
obj->div( no1 = number1 no2 = number2 ).

ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
lcl_example=>main( ).

After executing the above code we get the following output.

• Output Parameters: Output parameters are specified after the EXPORTING


addition to the METHODS or CLASS-METHODS statement, or are declared by
selecting Exporting in the Type column on the Parameters tab page in the Class
Builder. The output parameters contain values returned from the method. These
values originate within method and they are exported out of it. When a method is
called, the value of the assigned actual parameter (parameter passed from calling
statement) is not assigned to an output parameter for which pass by value is
defined. Output parameters can be overwritten in the method. If the method is
exited without errors using ENDMETHOD or RETURN, the output parameter is
passed to the actual parameter.

Following example demonstrate the use of output parameters.

REPORT z_oop_methd02.

PARAMETERS: number1 TYPE i,


number2 TYPE i,
operand TYPE c.

CLASS lcl_example DEFINITION.


PUBLIC SECTION.

195
CLASS-METHODS main.
METHODS perform_arithmetic
"means the parameters will travel
"in from program into method during
"calling where these will act as exporting

IMPORTING
no1 TYPE i
no2 TYPE i
op TYPE c
"means the parameter will travel
"out from the method into the
"program at calling where it will
"acts as importing

EXPORTING
rslt TYPE i.

ENDCLASS.

CLASS lcl_example IMPLEMENTATION.

METHOD perform_arithmetic.
IF op = '+'.
rslt = no1 + no2.
ELSEIF op = '-'.
rslt = no2 - no1.
ELSEIF op = '*'.
rslt = no1 * no2.
ELSEIF op = '/'.
rslt = no1 DIV no2.
ELSE.
MESSAGE 'Invalid Operator' TYPE 'I'.
ENDIF.
ENDMETHOD.

METHOD main.
DATA obj TYPE REF TO lcl_example.
DATA result TYPE i.

CREATE OBJECT obj.

"here EXPORTING specifies that the parameters


"will travel out from the program and at the
"same time these will be importing to the method

obj->perform_arithmetic( EXPORTING
no1 = number1
no2 = number2
op = operand
"means this parameter

196
"will travel in from method
"into program where it is
"acting as exporting

IMPORTING
rslt = result ).

WRITE: 'Result = ', result.

ENDMETHOD.

ENDCLASS.

START-OF-SELECTION.
lcl_example=>main( ).

Following is the output.

• Input / Output Parameters: I/O parameters are specified after the CHANGING
addition to the METHODS or CLASS-METHODS statement or are declared by
selecting Changing in the Type column on the Parameters tab page in the Class
Builder. I/O parameters contain values that are passed into the method, changed
by the code within the method and then returned. These values originate outside
the method; they are passed into it, and passed back. When a method is called, the
value of the assigned actual parameter (parameter passed from calling statement)
is assigned to the I/O parameter, and if the method is exited without errors using
ENDMETHOD or RETURN, the I/O parameter is passed to the actual parameter. I/O
parameters can be overwritten in the method.

197
The previous example is repeated with the use of I/O parameters.

REPORT z_oop_methd03.

PARAMETERS: number1 TYPE i,


number2 TYPE i,
operand TYPE c.

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
METHODS perform_arithmetic
CHANGING
no1 TYPE i
no2 TYPE i
op TYPE c
rslt TYPE i.

ENDCLASS.

CLASS lcl_example IMPLEMENTATION.

METHOD perform_arithmetic.
IF op = '+'.
rslt = no1 + no2.
ELSEIF op = '-'.
rslt = no2 - no1.
ELSEIF op = '*'.
rslt = no1 * no2.
ELSEIF op = '/'.
rslt = no1 DIV no2.
ELSE.
MESSAGE 'Invalid Operator' TYPE 'I'.
ENDIF.
ENDMETHOD.

METHOD main.
DATA obj TYPE REF TO lcl_example.
DATA result TYPE i.

CREATE OBJECT obj.

obj->perform_arithmetic( CHANGING
no1 = number1
no2 = number2
op = operand
rslt = result ).

WRITE: 'Result = ', result.

ENDMETHOD.

198
ENDCLASS.

START-OF-SELECTION.
lcl_example=>main( ).

Following is the output of the above code listing.

• Return Value: A method can have only one return value, for which pass by value
must be declared. This return value can be declared after the RETURNING
addition to the METHODS or CLASS-METHODS statement, or by selecting
Returning in the Type column on the Parameter tab page in the class builder. A
return value is handled in the same way that an output parameter is handled in the
method; however, a method with a return value is a functional method, which, in
addition to the return value, can have only input parameters. A functional method
can be used in operand operations. The return value is then used in these
operations.

The following example shows the use of return value.

REPORT z_oop_methd04.

CLASS lcl_math DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
METHODS factorial
IMPORTING
n TYPE i
RETURNING
"value addition specify that
"fact will be passed by value
value(fact) TYPE i.
ENDCLASS.

CLASS lcl_math IMPLEMENTATION.

199
METHOD factorial.
fact = 1.
IF n = 0.
RETURN.
ELSE.
DO n TIMES.
fact = fact * sy-index.
ENDDO.
ENDIF.
ENDMETHOD.

METHOD main.
DATA obj TYPE REF TO lcl_math.
DATA rslt TYPE i.

CREATE OBJECT obj.

rslt = obj->factorial( 1 ).
WRITE: 'Factorial of 4 = ', rslt
RIGHT-JUSTIFIED.

rslt = obj->factorial( 3 ).
WRITE: / 'Factorial of 10 = ', rslt
RIGHT-JUSTIFIED.

rslt = obj->factorial( 7 ).
WRITE: / 'Factorial of 11 = ', rslt
RIGHT-JUSTIFIED.

ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
lcl_math=>main( ).

200
Following is the output produced by above listing.

When we declare a parameter, we must select the type that matches the behavior
of that parameter exactly. A parameter that is received but not changed by the
method is an input parameter. A parameter that is output but is not received is an
output parameter or a return value. A parameter that is received changed and
output is an I/O parameter. Figure below shows how parameters are passed and
received from the method.

Kind of Parameter Passing

The formal parameter is passed either ass pass by value or pass by reference.

• Pass by Value: With pass by value, a local data object is created as a copy of the
actual parameter for each formal parameter when the method is called. In case of
input parameters and I/O parameters, the value of the actual parameter is assigned
to this data object. The value of the formal parameter is only assigned to output
parameters, I/O parameters and return values if the method is exited without
errors using ENDMETHOD or RETURN. The syntax of pass by value is shown
below using the example of the return value fact:

201
… RETURNING VALUE(fact) …

• Pass by Reference: With pass by reference, a reference to the actual parameter is


passed to the method for each formal parameter for which an actual parameter is
specified when we call the method, regardless of the parameter type. The method
thus uses the actual parameter itself, and changes to formal parameters have a
direct effect on the actual parameter. Following is the syntax of pass by reference
using the example of input parameter ipara:

… IMPORTING REFERENCE(ipara) …

In the Class Builder, we define the kind of parameter passing by selecting the
Pass by value check box on the Parameters tab page or leaving this blank. Thus
pass by reference is the default transfer type, which is used unless a different type
is specified, both in the syntax and in the Class Builder.
The method should always be programmed in such a way that the behavior of its
parameters corresponds to the semantics defined by the parameter type:

o Do not execute read access to an output parameter that is passed by


reference because its initial value is not defined.
o If you add lines to an internal table or extend a string that is defined as an
output parameter that is passed by reference, you must initialize the
parameter before the first access.

Pass by reference always perform better than pass by value because no data object
has to be created when a procedure is called and no data transport takes place. The
example in listing below shows the usage of by value and by reference
parameters.

REPORT z_oop_methd05.

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.

PRIVATE SECTION.
METHODS: meth_byval
IMPORTING
value(idx) TYPE i,
meth_byref
IMPORTING
reference(idx) TYPE i.

DATA msg TYPE string.


ENDCLASS.

CLASS lcl_example IMPLEMENTATION.


METHOD main.

202
DATA obj TYPE REF TO lcl_example.
CREATE OBJECT obj.

WRITE: 'Calling method by Value'.


WRITE: / '======================='.

obj->meth_byval( EXPORTING
idx = sy-index ).
SKIP.
WRITE: 'Calling method by Rseference'.
WRITE: / '============================'.

obj->meth_byref( EXPORTING
idx = sy-index ).
ENDMETHOD.

METHOD meth_byval.
DO 3 TIMES.
msg = idx.
CONCATENATE 'meth_byval: ' msg INTO msg.
WRITE: / msg.
ENDDO.
ENDMETHOD.

METHOD meth_byref.
DO 3 TIMES.
msg = idx.
CONCATENATE 'meth_byref: ' msg INTO msg.
WRITE: / msg.
ENDDO.
ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
lcl_example=>main( ).

Following is the output of the above example.

203
Parameter Typing

Typing means that to assign a type to a formal parameter. The syntax used for this
purpose is a TYPE or LIKE addition, which must be specified after each formal
parameter. For example:

METHODS my_meth EXPORTING


param TYPE data_type …

In Class Builder, fill the Typing (Type, Type Ref To, or Like) and Reference type columns
accordingly on the Parameters tab page in order to specify the type.

204
The type must be accessible to all users of the method; we can specify built-in ABAP
types, global types from the ABAP Dictionary or types from the public visibility section
of a global class for public methods. With protected methods, additional types from the
protected visibility section of the class can also be used, while types from the private
visibility section and local types from the class pool can be used for private method types
only.

The main difference between typing and data declaration is that a formal parameter is
assigned its actual data type only when it is linked to an actual parameter when a method
is called. All technical properties of the actual parameter are then passed to the formal
parameter.

In order for an actual parameter to be passed, its data type must match the typing
(technical properties must be compatible) of the formal parameter. The typing of a formal
parameter may be complete or generic. For complete typing, use TYPE to refer to a
complete data type or LIKE to refer to a data object. For generic typing, we can use the
built-in generic types (any, any table, data, ……). Internal table types are also
generic if the table key is not fully defined. If we need to use a generic type, we should
always be as specific as possible, use generic types line numeric, simple and
xsequence instead of any. Following example demonstrate the usage of generic
typing.

REPORT z_oop_methd06.

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
METHODS meth1
IMPORTING
ipar TYPE any.
ENDCLASS.

CLASS lcl_example IMPLEMENTATION.


METHOD main.
DATA obj TYPE REF TO lcl_example.
CREATE OBJECT obj.

obj->meth1( EXPORTING
ipar = '10.4' ).

ENDMETHOD.
METHOD meth1.
DATA: str TYPE string,
num TYPE i,
flt TYPE f.

str = ipar.
WRITE: 'Value of in string format = ',
str RIGHT-JUSTIFIED.

205
SKIP.
num = ipar.
WRITE: / 'Value of in integer format = ',
num LEFT-JUSTIFIED.
SKIP.
flt = ipar.
WRITE: / 'Value of in float format = ',
flt LEFT-JUSTIFIED.
ENDMETHOD.

ENDCLASS.

START-OF-SELECTION.
lcl_example=>main( ).

Following is the output.

Supply Type of Parameter

For every formal parameter that awaits a value (Input parameters and I/O parameters), an
actual parameter must be specified when the method is called. The assignment of actual
parameters to output parameters and return values is always optional.

For input parameters and I/O parameters, this rule can be avoided by declaring the
parameter as optional. The syntax is shown below, using the example of I/O parameter:

METHODS my_meth CHANGING


cpare type data_type OPTIONAL …
Or

METHODS my_meth CHANGING


cpare type data_type DEFAULT
data_object …

An optional formal parameter for which no actual parameter is specified is initialized in


accordance with its type. With addition DEFAULT the value and type of an appropriately
specified replacement parameter data_object are copied.

206
In the Class Builder, we can make a formal parameter optional by selecting the Optional
column, or by entering a value in the Default value column.

It is recommended that to make all formal parameters optional, with the exception of
those for which a different entry is actually required each time the method is called.
Otherwise, we will force the callers to specify unnecessary actual parameters, for which
type-specific auxiliary variables often have to be created.

The following program demonstrates the use of DEFAULT parameter.

REPORT z_oop_methd07.

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.

PRIVATE SECTION.
METHODS print IMPORTING
iname TYPE string
iclass TYPE string DEFAULT '10th'.
ENDCLASS.

CLASS lcl_example IMPLEMENTATION.


METHOD print.
WRITE: 'Your name is: ', iname.

IF iclass IS NOT SUPPLIED.


WRITE: / 'Your class is: ', iclass COLOR 6.
ELSE.
WRITE: / 'Your class is: ', iclass.
ENDIF.

SKIP.
ENDMETHOD.

METHOD main.
DATA obj TYPE REF TO lcl_example.
CREATE OBJECT obj.

obj->print( EXPORTING
iname = 'Jamil'
iclass = '5th' ).

207
obj->print( EXPORTING
iname = 'Asghar Khan' ).

obj->print( EXPORTING
iname = 'Mudasair'
iclass = '2nd' ).

obj->print( EXPORTING
iname = 'Khadija' ).

ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
lcl_example=>main( ).

Following is the output produced by the above listing.

Method Calls
Static Method Calls

Statically method can be invoked as component of a class (static) or an object. To call an


instance method we have to use the instance component selector (->) and for static
method calls we have to use the static component selector (=>).

obj->my_math( ).

Or

Class_name=>my_math( ).

208
If a method has several non-optional input parameters, the statement is as follows; here a
data object is explicitly assigned to each input parameter.

my_math( ipara1 = dobj1


ipara2 = dobj2 … ).

If actual parameters are to be assigned to any formal parameters, the syntax is as follows:

my_meth( EXPORTING
ipara1 = dobj1
ipara2 = dobj2 …
IMPORTING
opara1 = dobj1
opara2 = dobj2 …
CHANGING
cpara1 = dobj1
cpara2 = dobj2 … ).

With EXPORTING, we supply the input parameters defined with IMPORTING. With
IMPORTING, we receive values from output parameters defined with EXPORTING.
With CHANGING, we assign the actual parameters to the I/O parameters defined with
CHANGING. The equal sign is not an assignment operator in this case. Instead, its
function is to bind actual parameters to formal parameters.

Functional Method Calls

A functional method can have any number of input parameters and only one return value
that is passed by value. The functional methods are intended to be used in operand
position. To call the function method the RECEVING addition can be used to receive the
return value as:

my_meth( EXPORTING
ipara1 = dobj1
ipara2 = dobj2 ….
RECEIVING
rpara = dobj ).

However, this statement is hardly used in practice. The functional equivalent for the
above statement is as follows:

dobj = my_meth( ipara1 = dobj1 ipara2 = dobj2 … ).

When the statement is executed the method is called and the return value is used as an
operand. In following example two functional methods get_area and get_volume
are implemented.

209
REPORT z_oop_methd08.

SELECTION-SCREEN BEGIN OF SCREEN 100.


PARAMETERS: p_radius TYPE i,
p_height TYPE i.
SELECTION-SCREEN END OF SCREEN 100.

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS.

CLASS lcl_cylinder DEFINITION.

PUBLIC SECTION.
METHODS: get_area RETURNING
value(r_area) TYPE f,
get_volume RETURNING
value(r_volume) TYPE f.

CONSTANTS pi TYPE f VALUE '3.14159'.


DATA: radius TYPE f,
height TYPE f.
ENDCLASS.

CLASS lcl_cylinder IMPLEMENTATION.

METHOD get_area.
r_area = pi * me->radius ** 2.
ENDMETHOD.

METHOD get_volume.
r_volume = me->get_area( ) * me->height.
ENDMETHOD.

ENDCLASS.

CLASS lcl_example IMPLEMENTATION.

METHOD main.
DATA: obj TYPE REF TO lcl_cylinder,
volume TYPE string.
CALL SELECTION-SCREEN 100 STARTING AT 50 10.

IF sy-subrc = 0.
CREATE OBJECT obj.
obj->radius = p_radius.
obj->height = p_height.

volume = obj->get_volume( ).
WRITE: 'Volumene: ', volume.

210
ENDIF.
ENDMETHOD.

ENDCLASS.

START-OF-SELECTION.
lcl_example=>main( ).

Following is the output of above code.

Dynamic Method Call

To call a method dynamically we must use the language element CALL METHOD. The
method to be called can be specified by dynamic token specifications in various forms.
The syntax for the dynamic token specification is usually such that instead of the static
syntax, a bracketed identifier is given that contains the actual syntax:

… (identifier) …

Dynamic method call is also known as Dynamic Invoke. The dynamic method call can be
in the form of as:

CALL METHOD { (meth)_name


| obj->(meth_name)
| (class_name)=>( meth_name)
| class=>(meth_name)
| (class_name)=>meth_name}
[PARAMETER-TABLE ptab].

211
The PARAMETER-TABLE is used to assign actual parameters to all formal parameters of
a dynamically called method. For ptab, specify a hashed table of table type
ABAP_PARMBIND_TAB or of row type ABAP_PARMBIND from ABAP type group
(ABAP program that contains the definitions of globally visual data types and constants
and that is loaded via the usage of its data types and constants). During execution of the
CALL METHOD statement, this table must contain exactly one row for every non-
optional formal parameter and can contain exactly one row for every optional formal
parameter. The table columns are:

• NAME of type c and length 30 for the name of the respective formal parameter in
uppercase letters.
• KIND of type c of length 1 for the kind of the formal parameter (EXPORTING,
IMPORTING, CHANGING, RECEIVING).
• VALUE of type REF TO data as a pointer to an appropriate actual parameter.

Listing in the following example demonstrates the dynamic method call.

REPORT z_oop_methd09.

"CL_GUI_FRONTEND_SERVICES class of the class library


"contains methods for processing files
PARAMETERS: p_class TYPE string
DEFAULT 'CL_GUI_FRONTEND_SERVICES',
p_meth TYPE string
DEFAULT 'DIRECTORY_EXIST',
p_in TYPE string
DEFAULT 'DIRECTORY',
p_value TYPE string
DEFAULT 'C:\WINDOWS',
p_out TYPE string
DEFAULT 'RESULT'.

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
"TYPE-POOLS declares the data types and constants
"of type group, abap is the predefined type group
"the table type abap_func_parmbind_tab belongs to
"the type group abap
TYPE-POOLS abap.
ENDCLASS.

CLASS lcl_example IMPLEMENTATION.


METHOD main.

DATA: out_value TYPE string,


parameter TYPE abap_parmbind,
parameters TYPE abap_parmbind_tab,
error TYPE REF TO cx_root,

212
msg TYPE string.

"set tabl components


parameter-name = p_in.
"cl_abap_objectdescr is a global class, provides
"Runtime Type Services
parameter-kind = cl_abap_objectdescr=>exporting.

GET REFERENCE OF p_value INTO parameter-value.


INSERT parameter INTO TABLE parameters.

parameter-name = p_out.
parameter-kind = cl_abap_objectdescr=>returning.

GET REFERENCE OF out_value INTO parameter-value.


INSERT parameter INTO TABLE parameters.

TRY.

CALL METHOD (p_class)=>(p_meth)


PARAMETER-TABLE
parameters.

CONCATENATE 'Return Value: ' out_value INTO msg.


MESSAGE msg TYPE 'I'.

CATCH cx_sy_dyn_call_error INTO error.


MESSAGE error TYPE 'I' DISPLAY LIKE 'E'.
ENDTRY.

ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
lcl_example=>main( ).

Following is the output of the above example.

213
Class Instantiation

The addition CREATE defines the context in which class can be instantiated that is, where
the CREATE OBJECT statement can be executed for that class. Publicly instantiated
class allows any user to create objects. Classes with protected instantiation allow the
creation of objects in methods of subclasses. In classes with private instantiation, it is
only the class itself that can create objects. The syntax that controls the instantiation of a
class is as follows:

CLASS myclass DEFINITION


CREATE PUBLIC|PROTECTED|PRIVAE.
.........
ENDCLASS.

If we don’t specify any value, the class can be publicly instantiated by default. In the
following example the demo class is declared with private instantiation.

REPORT z_oop_class02.

CLASS lcl_demo DEFINITION CREATE PRIVATE.

PUBLIC SECTION.
DATA attr TYPE c LENGTH 20.

ENDCLASS.

CLASS lcl_example DEFINITION.

214
PUBLIC SECTION.
CLASS-METHODS main.

ENDCLASS.

CLASS lcl_example IMPLEMENTATION.

METHOD main.

DATA obj TYPE REF TO lcl_demo.


CREATE OBJECT obj.

obj->attr = 'ABAP Objects'.

WRITE: 'Value of attr = ', obj->attr.

ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
lcl_example=>main( ).

On compilation the above code produces the following error.

Multiple Instantiation

The example below shows how to manage any number of objects for the same class. The
handling of several objects via an internal table demonstrates the synthesis from the 4GL
language ABAP and the OO language elements of ABAP Objects. Other OO languages
such as Java do not provide any direct language elements that would solve the task shown
here.

REPORT y_oop_minst.

CLASS zcl_vehicle DEFINITION.

PUBLIC SECTION.
METHODS accelerate IMPORTING delta TYPE i.
METHODS show_speed.

PRIVATE SECTION.

215
DATA speed TYPE i.

ENDCLASS.

CLASS zcl_vehicle IMPLEMENTATION.

METHOD accelerate.
speed = speed + delta.
ENDMETHOD.

METHOD show_speed.
DATA output TYPE string.
output = speed.
MESSAGE output TYPE 'I'.
ENDMETHOD.

ENDCLASS.

CLASS lcl_demo DEFINITION.

PUBLIC SECTION.
CLASS-METHODS main.

ENDCLASS.

CLASS lcl_demo IMPLEMENTATION.

METHOD main.

DATA: vehicle TYPE REF TO zcl_vehicle,


i_vtab TYPE TABLE OF REF TO zcl_vehicle,
n TYPE i VALUE 5,
speed TYPE i.

DO n TIMES.
CREATE OBJECT vehicle.
speed = sy-index * 10.
vehicle->accelerate( delta = speed ).

APPEND vehicle TO i_vtab.


ENDDO.

LOOP AT i_vtab INTO vehicle.


vehicle->show_speed( ).
ENDLOOP.

ENDMETHOD.

ENDCLASS.

216
START-OF-SELECTION.
lcl_demo=>main( ).

Following is the output of above listing.

Object Creation in a Factory Method

Factory method is an OO design pattern, and is often used to refer to any method whose
main purpose is creation of objects. Example below demonstrates the factory method.

REPORT z_oop_facmthd.

CLASS lcl_vehicle DEFINITION CREATE PRIVATE.


PUBLIC SECTION.
"RETURNING defines a formal parameter ref
"as a return value. The return value must
"be passed by value with VALUE.

CLASS-METHODS create RETURNING value(ref)


TYPE REF TO lcl_vehicle.

METHODS: accelerate IMPORTING delta TYPE i,


show_speed.

PRIVATE SECTION.
DATA speed TYPE i.
ENDCLASS.

CLASS lcl_demo DEFINITION.

217
PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS.

CLASS lcl_vehicle IMPLEMENTATION.


METHOD create.
CREATE OBJECT ref.
ENDMETHOD.

METHOD accelerate.
"me is an implicitly created local
"reference variable, which points to the
"instance in which the method is currently
"being executed. The static type of me is
"the class in which the instance method is
"implemented
me->speed = me->speed + delta.
ENDMETHOD.

METHOD show_speed.
DATA output TYPE string.

output = me->speed.
MESSAGE output TYPE 'I'.
ENDMETHOD.

ENDCLASS.

CLASS lcl_demo IMPLEMENTATION.


METHOD main.
DATA veh_obj TYPE REF TO lcl_vehicle.

"create the object and assign it to


"veh_obj reference
veh_obj = lcl_vehicle=>create( ).

veh_obj->accelerate( delta = 100 ).


veh_obj->show_speed( ).

ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
lcl_demo=>main( ).

Following is the out put produced by the above code.

218
Friends Classes (Suspending Encapsulation)

An external user can only access the public components of a class. However, in some
cases, classes must cooperate very closely so that they need to access the protected and
private components of each other. To do this we can use the concept of friendship
between classes.

A class can offer friendship to other classes (and interfaces) by using the FRIENDS
addition in the class definition part behind which all classes (and interfaces) are listed are
granted friendship. Granted friendship is a one-side process. A class that grants friendship
is not automatically a friend of its friends. Inheritors of friends also become friends;
however, the granting of friendship can not be inherited. The friend of a super class is not
automatically the friend of its subclasses.

A friendship should be used when a class is used as a container of data, storing the
services of classes in specific service class (agents) and in test classes of ABAP Unit. The
FRIENDS must be specified as the last after the other additions. Following is the syntax.

CLASS c1 DEFINITION.
.........
ENDCLASS.

.....................

CLASS myclass DEFINITION


CREATE PRIVAE FRIENDS c1.
.........
ENDCLASS.

219
In listing below the lcl_vehicle_agent is service class which must be declared as a
friend of lcl_vehicle class.

REPORT z_oop_friend.

CLASS lcl_vehicle_agent DEFINITION DEFERRED.

CLASS lcl_vehicle DEFINITION CREATE PRIVATE


FRIENDS lcl_vehicle_agent.

PUBLIC SECTION.
METHODS: accelerate IMPORTING delta TYPE i,
show_speed.

PRIVATE SECTION.
DATA speed TYPE i.

ENDCLASS.

CLASS lcl_example DEFINITION.

PUBLIC SECTION.
CLASS-METHODS main.

ENDCLASS.

CLASS lcl_vehicle_agent DEFINITION.

PUBLIC SECTION.
CLASS-METHODS create RETURNING value(ref)
TYPE REF TO lcl_vehicle.

ENDCLASS.

CLASS lcl_vehicle_agent IMPLEMENTATION.

METHOD create.
CREATE OBJECT ref.
ENDMETHOD.

ENDCLASS.

CLASS lcl_vehicle IMPLEMENTATION.

METHOD accelerate.
me->speed = me->speed + delta.
ENDMETHOD.

METHOD show_speed.
DATA output TYPE string.

220
output = me->speed.
WRITE: 'Vehicle Speed is: ', output.
ENDMETHOD.

ENDCLASS.

CLASS lcl_example IMPLEMENTATION.

METHOD main.
DATA veh_obj TYPE REF TO lcl_vehicle.

veh_obj = lcl_vehicle_agent=>create( ).
veh_obj->accelerate( delta = 100 ).
veh_obj->show_speed( ).
ENDMETHOD.

ENDCLASS.

START-OF-SELECTION.
lcl_example=>main( ).

If a local class is referred to within a class and the local class hasn’t been declared yet, it
must be made known using local CLASS DEFINITION DEFERRED statement. This is
because; the ABAP compiler compiles a program in one single process. If we don’t
publish the local class, the FRIENDS addition would cause a syntax error due to an
unknown class. Following is the output of the above listing.

Garbage Collection

Objects occupy space in the main memory. If they are no longer needed, they can and
should be deleted. The garbage collector or GC of the ABAP runtime environment is
responsible for the delectation of objects. The GC deletes objects that are no longer
referenced by reference variables. The GC is called periodically by the ABAP runtime
environment. It traces reference variables of deleted objects. This means, if an object that
is no longer referenced contains attributes of the reference variable type, its references are
traced by the GC. If no reference variable points to the objects found in this process,
those objects are deleted as well.

221
We can explicitly initialize references to objects using the CLEAR statement. Other
mechanisms that can cause references to objects to disappear are for example; when a
reference is assigned, the original reference in the target variable is lost, or a reference
variable is a local variable of a method that is deleted when the method ends.

On the other hand, we should note that many references to objects can exists – that keep
the objects alive. For example, the methods of an object can be registered as event
handlers or objects are managed or used by framework that can not be accessed directly.
To delete these kinds of references, event handlers must be deregistered and special
methods of the frameworks must be called. Otherwise, memory leaks can occurs which
may result in memory bottlenecks, particularly if many objects or large objects are used.

Thus, always release unused objects for the GC and use Memory Inspector too to check if
the garbage collection was successful.

Constructors

A constructor is a special method that is executed automatically by the runtime


environment. Constructors are used to put an object into a defined initial status. As with
all components of classes, we distinguish between instance constructors and static
constructors.

Instance Constructor

Instance Constructor is a predefined method of class called constructor. This method


is automatically executed once, immediately after the creation of an object of the class.
Thus, instance constructor serves to initialize individual instances. It must be declared
and implemented like a usual method. The instance constructor is required to be declared
in the public visibility section. However, the actual visibility is determined by where the
class can be instantiated, which is defined using the CREATE addition of CLASS
DEFINITION. The parameter interface of an instance constructor is limited to input
parameters (IMPORTING), because the instance constructor is exclusively used to define
an object status and is not supposed to provide any other behavior. The syntax for
instance constructor of local classes is:

CLASS lcl_myclass DEFINITION


CREATE PUBLIC|PROTECTED|PRIVATE.
PUBLIC SECTIONS.
METHODS constructor
[IMPORTING I TYPE tye … ]
…………………
ENDCLASS.

CLASS lcl_myclass IMPLEMENTATION.


METHOD constructor.
…………

222
ENDMETHOD.
ENDCLASS.

To create the constructor for global classes, we can select the Edit  Create Constructor
function or the Constructor from application toolbar.

To fill the input parameters of the instance constructor with values, the CREATE
OBJECT statement contains an addition:

CREATE OBJECT obj_ref EXPORTING


i = a.

Each non-optional input parameter i must be linked to an actual parameter a via the =
sign after EXPORTING. If an exception occurs in an instance constructor, the created
object will be deleted immediately during the execution of the CREATE OBJECT
statement, and the corresponding reference variable is set to its initial value.

The following example shows the use of the instance constructor.

REPORT z_oop_inst_construct.

CLASS lcl_vehicle DEFINITION.


PUBLIC SECTION.
METHODS:
constructor IMPORTING
icolor TYPE string,
accelerate IMPORTING
delta TYPE i,
show_speed.

PRIVATE SECTION.
DATA: color TYPE string,
speed TYPE i.
ENDCLASS.

CLASS lcl_vehicle IMPLEMENTATION.

METHOD constructor.
me->color = icolor.
ENDMETHOD. "constructor

223
METHOD accelerate.
me->speed = me->speed + delta.
ENDMETHOD.

METHOD show_speed.
DATA msg TYPE string.
msg = me->speed.
CONCATENATE me->color ':' msg INTO msg.
MESSAGE msg TYPE 'I'.
ENDMETHOD.

ENDCLASS.

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS.

CLASS lcl_example IMPLEMENTATION.


METHOD main.

DATA:
red_v TYPE REF TO lcl_vehicle,
blue_v TYPE REF TO lcl_vehicle,
green_v TYPE REF TO lcl_vehicle.

CREATE OBJECT:
red_v EXPORTING
icolor = 'Red',
blue_v EXPORTING
icolor = 'Blue',
green_v EXPORTING
icolor = 'Green'.

red_v->accelerate( 100 ).
blue_v->accelerate( 200 ).
green_v->accelerate( 300 ).

red_v->show_speed( ).
blue_v->show_speed( ).
green_v->show_speed( ).

ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
lcl_example=>main( ).

Following is the output of the above code listing.

224
Static Constructor

The static constructor is a predefined method of a class called class_constructor.


This method is automatically executed once for each class in a program before the class
is accessed for the first time. The static constructor is used to initialize the static attributes
of a class. The static constructor must always be declared in the public visibility section
of the class. A static constructor does not have any parameter interface. We use the static
constructor to apply the Singleton pattern. The syntax for the static constructor of local
classes is:

CLASS lcl_myclass DEFINITION.


PUBLIC SECTION.
CLASS-METHOD class_constructor.
…………….
ENDCLASS.

CLASS lcl_myclass IMPLEMENTATION.


METHOD class_constructor.
…………….
ENDMETHOD.
ENDCLASS.

To implement the static constructor for global classes we can select the Edit  Create
Class Constructor function or the Class Constructor from application toolbar.

Following listing implements the static constructor.

REPORT z_oop_static_construct.

CLASS lcl_vehicle_agent DEFINITION DEFERRED.

CLASS lcl_vehicle DEFINITION CREATE PRIVATE


FRIENDS lcl_vehicle_agent.

225
PUBLIC SECTION.
METHODS:
accelerate IMPORTING
delta TYPE i,
show_speed.

PRIVATE SECTION.
DATA speed TYPE i.
ENDCLASS.

CLASS lcl_vehicle IMPLEMENTATION.


METHOD accelerate.
me->speed = me->speed + delta.
ENDMETHOD.

METHOD show_speed.
DATA msg TYPE string.
msg = me->speed.
MESSAGE msg TYPE 'I'.
ENDMETHOD.
ENDCLASS.

CLASS lcl_vehicle_agent DEFINITION CREATE PRIVATE.


PUBLIC SECTION.
CLASS-DATA agent TYPE REF TO lcl_vehicle_agent
READ-ONLY.
CLASS-METHODS class_constructor.
METHODS create
RETURNING value(ref)
TYPE REF TO lcl_vehicle.
ENDCLASS.

CLASS lcl_vehicle_agent IMPLEMENTATION.

METHOD class_constructor.
CREATE OBJECT lcl_vehicle_agent=>agent.
ENDMETHOD. "class_constructor

METHOD create.
CREATE OBJECT ref.
ENDMETHOD.

ENDCLASS.

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS.

CLASS lcl_example IMPLEMENTATION.


METHOD main.

226
DATA:
agent TYPE REF TO lcl_vehicle_agent,
vehicle TYPE REF TO lcl_vehicle.

agent = lcl_vehicle_agent=>agent.
vehicle = agent->create( ).

vehicle->accelerate( 100 ).
vehicle->show_speed( ).
ENDMETHOD.
ENDCLASS.

START-OF-SELECTION.
lcl_example=>main( ).

Following is the output of the above example.

Destructors

Destructor is class method which is called when the object is deleted by the garbage
collection. In fact, many OOP languages contain these kinds of methods. For several
reasons like performance, transaction concept etc, ABAP Objects doesn’t provide any
destructors for application development.

Local Declarations in Class Pool


Class pool is a container for exactly one global class and more than one data types and
local object types (local classes and interfaces). All the reusable code is programmed
here. A class pool is loaded into memory by using the global class, for example, a public
method of global class can be called from another ABAP program or it can be linked with
a transaction code. They are declared with the CLASS-POOL statement but as it is
created with Class Builder (SE24) of ABAP Workbench, which means it is generally not
displayed as a single continues source code.

It is obvious that we can create local types, classes and interfaces in class pool, however;
local data and processing blocks other than the methods are not permitted.

227
To create a local type in a class pool, select GotoClass-local TypeLocal Class
definitions/Types or Local Types from application toolbar in the class builder. This takes
us to the ABAP Editor for an include program that is integrated in the global declaration
part of the class pool. Here we can define program local types using TYPES statement.
Local types defined this way can be referenced only in private visibility section of the
global declaration part of the global class.

The local classes are declared in the same include program as local types. To create a
local class in a class pool, we must also select GotoClass-local TypeLocal Class
definitions/Types or Local Types and to implement the local classes, select GotoClass-
local TypesLocal Class implementations or Implementation from the application
toolbar. This takes us to the ABAP Editor for an include program that is integrated in the
implementation part of the class pool.

We can use local classes to modularize a class pool beyond the methods of the global
class. In class pool local classes play the same roles as the local classes in other ABAP
programs. They are not visible from outside. If we want to access the protected and
private components of global class, we must declare it as a local friend of the class. To do
that, we can use the following special statement:

CLASS global_class DEFINITION

LOCAL FRIENDS ….. local_class ……

This statement does not have an associated ENDCLASS statement and can be contained in
the include for the local class definition. The modularization of a global class through
local classes of the class pool is a recommended procedure.

The following example demonstrates the use of local class in global class.

1. Goto transaction SE24.


2. Give a name and press create. A pop up window appears asking for short
description, instantiation (like Public, Private, Abstract and Protected) and type of
the class (normal ABAP Class). Select the appropriate class type. If you don’t
want to create any subclass of this class, then check the checkbox named “Final”.

228
3. Create Object Directory Entry dialog appears, assign the package and click save
to continue. The Object Directory is a directory of all the Repository Objects that
make up the SAP System. When you create an object, the corresponding object
directory entry is also created.

4. Next dialog prompt for transport request. The transport request our package
belongs to is already in the relevant field. Again Confirm it.
5. Now you will get the class builder screen.

229
6. From application toolbar select Local Types to define local class in the class pool.
Enter the following lines of code, save and exit the editor.

7. To implement the local class in class pool, select the Implementation option from
application toolbar and enter the following lines of code.

8. Click on methods tab. Give a method name, level (Instance or Static), visibility
(Public , protected or private ) and description.

230
9. Double click on method name and you will get an editor to perform the coding.
Enter the following code.

10. Save and activate the global class.


11. To consume the global class create report Z_GLBL_CLIENT and enter the
following code.

231
12. Following output is produced after executing the above code.

232
Inheritance
The inheritance mechanism for an OOP language provides options that help to reuse the
same or similar parts of a class, and create a hierarchy of classes. In object orientation,
inheritance refers to the specialization of classes by deriving subclasses (derived or child
classes) from super classes (base class or parent class). Derived or more specific classes
are referred to as Subclass, while more general classes are called superclasses.

ABAP Objects implements the concept of simple inheritance, according to this concept;
each class can have several subclasses but only one superclass. In simple inheritance,
inheritance relationships are represented by an inheritance tree. The root node of the
inheritance tree in ABAP Objects is the predefined, empty and abstract class object.
All classes in ABAP Objects that do not explicitly inherit from another class are implicit
direct subclasses of object.

When subclasses of explicitly defined classes are created, these inherit the components of
their superclasses and can add new components.

The relationship between a subclass and its superclass should always be expressed as “is-
a” relationship. For example a hexagon is-a shape. On the other hand the “has-a”
relationship also called aggregation or composition is based on usage, rather than
inheritance of a class. For example a horse has-a halter.

Creating Subclasses
Inheritance relationship can only be defined when a subclass is declared. A superclass has
no knowledge of any subclasses it may have. Only a subclass is aware that it is the
heir/inheritor of another class. The syntax for deriving a subclass from a superclass is as
follows:

CLASS sub_class DEFINITION


INHERITING FROM super_class.
................
ENDCLASS.

Any non-final class that is visible at this point can be specified for super_class. To
create a subclass in the Class Builder, select Superclass on the Properties tab page. Then
enter any non-final, global class as a superclass in the Superclass field. The Undo
inheritance and Change inheritance options allow to change the inheritance relationship.

233
For each class that doesn’t have an explicit INHERITING FROM addition, the system
implicitly adds the INHERITING FROM object addition, which means that any class
without an INHERITING addition is automatically a direct subclass of the object root
class.

The example below two classes car and truck are derived from vehicle class.

REPORT z_oop_inheritance.

CLASS lcl_vehicle DEFINITION.


PUBLIC SECTION.
METHODS:
accelerate IMPORTING
ivtype TYPE string
idelta TYPE i,
show_speed.

PROTECTED SECTION.
DATA: speed TYPE i,
vtype TYPE string.

ENDCLASS. "lcl_vehicle DEFINITION

CLASS lcl_vehicle IMPLEMENTATION.


METHOD accelerate.
me->speed = me->speed + idelta.
me->vtype = ivtype.
ENDMETHOD. "accelerate

METHOD show_speed.
DATA msg TYPE string.
msg = me->speed.
CONCATENATE vtype ' is travelling with speed = '
msg INTO msg.
WRITE msg.
ENDMETHOD. "show_speed
ENDCLASS. "lcl_vehicle IMPLEMENTATION

234
CLASS lcl_car DEFINITION
INHERITING FROM lcl_vehicle.
ENDCLASS. "lcl_car DEFINITIO

CLASS lcl_truck DEFINITION


INHERITING FROM lcl_vehicle.
PUBLIC SECTION.
METHODS: load IMPORTING
ifreight TYPE string,
unload.

PROTECTED SECTION.
DATA freight TYPE string.
ENDCLASS. "lcl_truck DEFINITIO

CLASS lcl_truck IMPLEMENTATION.


METHOD load.
me->freight = ifreight.
WRITE: 'Truck is loaded with', me->freight.
ENDMETHOD. "load

METHOD unload.
CLEAR me->freight.
WRITE: 'Truck is uloaded', me->freight.
ENDMETHOD. "unload
ENDCLASS. "lcl_truck IMPLEMENTATION

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS. "lcl_example DEFINITION

CLASS lcl_example IMPLEMENTATION.


METHOD main.
DATA: car_ref TYPE REF TO lcl_car,
truck_ref TYPE REF TO lcl_truck.

CREATE OBJECT: car_ref,


truck_ref.

car_ref->accelerate( EXPORTING
ivtype = 'Car'
idelta = 130 ).
car_ref->show_speed( ).
SKIP.
truck_ref->load( 'Gur' ).
SKIP.
truck_ref->accelerate( EXPORTING
ivtype = 'Truck'
idelta = 110 ).

235
truck_ref->show_speed( ).
SKIP.
truck_ref->unload( ).
ENDMETHOD. "main
ENDCLASS. "lcl_example IMPLEMENTATION

START-OF-SELECTION.
lcl_example=>main( ).

The lcl_car and lcl_truck classes both derived from lcl_vehicle. Therefore,
they inherit the attribute and methods of the lcl_vehicle class. Since speed is
declared in the PROTECTED SECTION, it is also visible in the subclasses. The
lcl_truck class is specialized with an additional attribute for freight and additional
methods for loading and unloading. Since lcl_car class objects are the same as that of
the lcl_vehicle class, since no methods have been added, lcl_car doesn’t require
an implementation part. Following is the output of the above code:

Visibility Sections in Inheritance


The public visibility section of a subclass contains all public components of all
superclasses, plus its own additional public components. These components can be
accessed externally using component selectors.

The protected visibility section of a subclass contains all protected components of all
superclass, plus its own additional protected components. These components cannot be
accessed externally using component selectors. From an external point of view, protected
is the same as private.

The private visibility section of subclass contains only the subclass’s own private
components. These components can only be accessed in the method implementations of
the subclass. The private components are also inherited in principle, but are not visible in
the subclass.

236
A superclass is not aware of any subclasses it may have. If we create a non-final class in
a class library and release it for use, we can never know as a developer, which subclasses
our class will eventually have other than those we define our self. If we then subsequently
add new components to the public or protected section of our class, and any of its
subclasses happen to have a component of its own with the same name, this become
syntactically incorrect. Therefore, it is only secure to add private components. To limit
the subclasses of a class to at least the same package, non-final classes should preferably
be organized in packages for which the Package Check as Server property is activated.
This ensures that only objects declared in the package interface of the package can be
addressed from other transportable packages. A package interface is a subset of the
visible development elements of a package that are visible externally. A package
interface can also contain development elements of a subpackage if they are included in a
package interface of the subpackage.

Method Redefinition
When a method is called in the subclass, it is executed in the same way it was
implemented in the superclass. However, since the main purpose of inheritance is to
specialize classes, the behavior of the method of a superclass may be too general for the
more specific purpose of the subclass. In some cases, the implementation of superclass
must be enhanced in the subclass, while in other instances; the implementation must be
completely changed. However, the semantics of the method must remain stable for the
external user; because all this user ever sees is the constant interface (including
documentation) and not the implementation itself.

Instance methods can be redefined in subclasses to specialize the behavior of subclass


objects. Static methods can not be redefined. Redefining methods means creating a new
implementation of the method is a subclass without changing the interface (ABAP
Objects doesn’t currently support method overloading; i.e. methods are redefined with
separate or changed parameter interface). When a method is redefined in a subclass, an
additional implementation is created, which hides the previous implementation when the
subclass and further subclasses are used.

Every reference that refers to an object of the subclass uses the redefined method. Like
the methods belonging to the subclass, a redefined method accesses the private attributes
of the subclass. The syntax for redefining an instance method in a subclass is as follows:

METHODS my_meth REDEFINITION.

This statement must be specified in the declaration part of the subclass in the same
visibility section as the actual declaration of the method is the superclass. The definition
of parameter interface is not repeated.

237
In the Class Builder, we redefine an inherited method by displaying it on the Methods
tab. To do so, we must use the UtilitiesSettings function of the Class Builder to select
the Display Inherited Components Also entry. Then, we must highlight the method and
select the Redefine function. Now we can navigate to the implementation in the same
way as with normal methods.

In the implementation of redefined method, we can use the pseudo reference (super->)
to access the original method of the direct superclass. This overrides the hiding of the
redefined method.

We can now apply method redefinition to our previous example of inheritance.

REPORT z_oop_methd_redef.

CLASS lcl_vehicle DEFINITION.


PUBLIC SECTION.
METHODS:
accelerate IMPORTING
idelta TYPE i,
show_speed.

PROTECTED SECTION.
DATA: speed TYPE i.

ENDCLASS. "lcl_vehicle DEFINITION

CLASS lcl_vehicle IMPLEMENTATION.


METHOD accelerate.
me->speed = me->speed + idelta.
ENDMETHOD. "accelerate

METHOD show_speed.
DATA msg TYPE string.
msg = me->speed.
WRITE msg.
ENDMETHOD. "show_speed
ENDCLASS. "lcl_vehicle IMPLEMENTATION

CLASS lcl_car DEFINITION


INHERITING FROM lcl_vehicle.
PUBLIC SECTION.

238
METHODS show_speed REDEFINITION.

ENDCLASS. "lcl_car DEFINITIO

CLASS lcl_car IMPLEMENTATION.


METHOD show_speed.
DATA msg TYPE string.
msg = me->speed.
CONCATENATE 'Car, Speed: ' msg INTO msg
RESPECTING BLANKS.
WRITE msg.
ENDMETHOD. "show_speed
ENDCLASS. "lcl_car IMPLEMENTATION

CLASS lcl_truck DEFINITION


INHERITING FROM lcl_vehicle.
PUBLIC SECTION.
METHODS: accelerate REDEFINITION,
show_speed REDEFINITION,
load IMPORTING
ifreight TYPE string,
unload.

PROTECTED SECTION.
DATA freight TYPE string.

PRIVATE SECTION.
CONSTANTS max_speed TYPE i VALUE '80'.
ENDCLASS. "lcl_truck DEFINITIO

CLASS lcl_truck IMPLEMENTATION.


METHOD accelerate.
super->accelerate( idelta ).

IF me->speed > lcl_truck=>max_speed.


me->speed = lcl_truck=>max_speed.
ENDIF.

ENDMETHOD. "accelerate

METHOD show_speed.
DATA msg TYPE string.
msg = me->speed.
CONCATENATE 'Truck with ' me->freight
', Speed: ' msg INTO msg
RESPECTING BLANKS.

WRITE msg.
ENDMETHOD. "show_speed

METHOD load.

239
me->freight = ifreight.
ENDMETHOD. "load

METHOD unload.
CLEAR me->freight.
WRITE: 'Truck is uloaded', me->freight.
ENDMETHOD. "unload
ENDCLASS. "lcl_truck IMPLEMENTATION

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS. "lcl_example DEFINITION

CLASS lcl_example IMPLEMENTATION.


METHOD main.
DATA: car_ref TYPE REF TO lcl_car,
truck_ref TYPE REF TO lcl_truck.
CREATE OBJECT: car_ref,
truck_ref.
car_ref->accelerate( 130 ).
car_ref->show_speed( ).
SKIP.
truck_ref->load( 'Gur' ).
truck_ref->accelerate( 110 ).
truck_ref->show_speed( ).
SKIP.
truck_ref->unload( ).
ENDMETHOD. "main
ENDCLASS. "lcl_example IMPLEMENTATION

START-OF-SELECTION.
lcl_example=>main( ).

Following is the out put of above listing.

240
Abstract Classes and Methods
An abstract class provides a common definition for a super class that multiple sub classes
can share. The syntax for defining an abstract class is:

CLASS my_class DEFINITION ABSTRACT.


………………………
ENDCLASS.

Abstract class can't be instantiated using CREATE OBJECT. Abstract class can have
both abstract and non-abstract methods. Derived class must implement all the abstract
methods. An abstract method can be defined as:

METHODS my_meth ABSTRACT.

An abstract method can’t be implemented in its own class, but only in a concrete
subclass. Class that's not abstract is called a concrete class. The method implementation
mechanism is same as we discussed in method redefinition section. The only difference
to a real redefinition is that we can not use the pseudo reference (super->) in the
method. Concrete methods can call the abstract methods because the names and
parameter interfaces are completely known.

In Class Builder, select Abstract in the Instantiation input field on the Properties tab as
shown below:

We can identify a method as an Abstract in Class Builder Detail View as:

241
The previous example can be implemented in abstract class as:

REPORT z_oop_abstract_cls.

CLASS lcl_vehicle DEFINITION ABSTRACT.


PUBLIC SECTION.
METHODS: accelerate IMPORTING
idelta TYPE i,
show_speed ABSTRACT.
PROTECTED SECTION.
DATA speed TYPE i.
ENDCLASS. "lcl_vehicle DEFINITION

CLASS lcl_vehicle IMPLEMENTATION.


METHOD accelerate.
me->speed = me->speed + idelta.
ENDMETHOD. "accelerate
ENDCLASS. "lcl_vehicle IMPLEMENTATION

CLASS lcl_car DEFINITION


INHERITING FROM lcl_vehicle.
PUBLIC SECTION.
METHODS show_speed REDEFINITION.
ENDCLASS. "lcl_car DEFINITIO

CLASS lcl_car IMPLEMENTATION.


METHOD show_speed.
DATA msg TYPE string.
msg = me->speed.
CONCATENATE 'Car speed is: ' msg
INTO msg RESPECTING BLANKS.
WRITE msg.
ENDMETHOD. "show_speed
ENDCLASS. "lcl_car IMPLEMENTATION

CLASS lcl_truck DEFINITION


INHERITING FROM lcl_vehicle.
PUBLIC SECTION.

242
METHODS: accelerate REDEFINITION,
show_speed REDEFINITION,
load IMPORTING
freight TYPE string,
unload.
PROTECTED SECTION.
DATA freight TYPE string.
PRIVATE SECTION.
CONSTANTS max_speed TYPE i VALUE '80'.
ENDCLASS. "lcl_truck DEFINITIO

CLASS lcl_truck IMPLEMENTATION.


METHOD accelerate.
super->accelerate( idelta ).
IF me->speed > lcl_truck=>max_speed.
me->speed = lcl_truck=>max_speed.
ENDIF.
ENDMETHOD. "accelerate
METHOD show_speed.
DATA msg TYPE string.
msg = me->speed.
CONCATENATE 'Truck with ' me->freight
', speed: ' msg INTO msg
RESPECTING BLANKS.
WRITE msg.
ENDMETHOD. "show_speed
METHOD load.
me->freight = freight.
ENDMETHOD. "load
METHOD unload.
CLEAR me->freight.
WRITE 'Truck is unloaded'.
ENDMETHOD. "unload
ENDCLASS. "lcl_truck IMPLEMENTATION

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS. "lcl_example DEFINITION

CLASS lcl_example IMPLEMENTATION.


METHOD main.
DATA: car_ref TYPE REF TO lcl_car,
truck_ref TYPE REF TO lcl_truck.
CREATE OBJECT: car_ref,
truck_ref.

car_ref->accelerate( 130 ).
car_ref->show_speed( ).
truck_ref->load( 'Potato' ).
SKIP.

243
truck_ref->accelerate( 110 ).
truck_ref->show_speed( ).
SKIP.
truck_ref->unload( ).
ENDMETHOD. "main
ENDCLASS. "lcl_example IMPLEMENTATION

START-OF-SELECTION.
lcl_example=>main( ).

Following is the output of the above code.

Final Classes and Methods


A class or instance method can be declared as final to protect it from uncontrolled
specialization. The syntax for defining a final class is:

CLASS my_class DEFINITION FINAL.


………………………
ENDCLASS.

Methods of a final class are implicitly final and cannot be explicitly declared as final. In
the Class Builder, we can create a final class by selecting the Final checkbox on the
Properties tab.

In a non-final class, individual instance methods can be declared as final. The syntax is:

METHODS my_meth FINAL.

244
In the Class Builder, we can identify an instance method as Final in the Detail View.

A final method can’t be redefined in subclasses. A final method can’t be abstract at the
same time. A class can be abstract and final at the same time, but only its static
components are usable in this case. Although we can declare instance components in such
a class, it is not recommended.

Static Attributes and Methods in Inheritance


A subclass can access the contents of the public and protected static attributes of all
superclasses or a superclass shares it’s public and protected static attributes with all
subclasses. Therefore, static attributes in inheritance are not assigned to a single class, but
to a path of the inheritance tree. Static attributes can be accessed from outside via class
component selector (=>) using all class names involved, or from inside in all affected
classes where a static attribute is visible. Changes to the value are visible in all relevant
classes. A static constructor is executed when a class is addressed for the first time. If a
static attribute is addressed via the class name of a subclass but declared in a superclass,
only the static constructor of the superclass is executed.

Static methods can’t be redefined in ABAP Objects, because static components should
occur exactly one in a inheritance path so that the can be shared by all subclasses.

Listing below shows a simple example.

REPORT z_oop_inhrt_static.

CLASS lcl_myclass1 DEFINITION.


PUBLIC SECTION.
CLASS-DATA attr TYPE string.
ENDCLASS. "lcl_myclass1 DEFINITION

245
CLASS lcl_myclass2 DEFINITION
INHERITING FROM lcl_myclass1.
ENDCLASS. "lcl_myclass2 DEFINITIO

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS. "lcl_example DEFINITION

CLASS lcl_example IMPLEMENTATION.


METHOD main.
lcl_myclass2=>attr = 'Static attributes demo'.
MESSAGE lcl_myclass1=>attr TYPE 'I'.
ENDMETHOD. "main
ENDCLASS. "lcl_example IMPLEMENTATION

START-OF-SELECTION.
lcl_example=>main( ).

After execution the following message box is displayed.

Constructors in Inheritance
Instance constructor is used to set the instance attributes of every single object during
instancing process, the static constructor are is responsible for the static attributes of the
class before the class is first accessed. Because a subclass inherits all attributes of its
superclasses in inheritance, this automatically begs the question “How can the
constructors ensure that the inherited attributes are initialized as well when the subclass is
used?”

Instance Constructors

Every class has a predefined instance constructor named constructor. Thus, instance
constructor deviate from the rule that there are only unique components names along the
path of the inheritance tree. Consequently, the instance constructors of the individual
classes of an inheritance tree must be completely independent of one another. To avoid
naming conflicts, the following rules apply:

246
• Instance constructors of superclasses cannot be redefined in subclasses.
• Instance constructors cannot be explicitly called via the constructor ( )
statement.

A subclass must ensure that the instance constructors of all superclasses are executed as
well. For this purpose, the instance constructor of every subclass must contain a call

super->constructor( … ).

of the instance constructor of the direct superclass, even if the constructor is not explicitly
declared. The only exceptions to this rule are the direct subclasses of the root node,
object.

In superclasses in which the instance constructor is not explicitly declared and


implemented, the implicitly existing implementation of the instance constructor is run. It
automatically ensures that the instance constructor of the next higher superclass is called.

The execution of a subclass instance constructor can be divided into three phases that are
presented in the comment lines of listing below.

METHOD constructor.
*Phase-1: Access to static attributes only
………………………………………….
*Phase-2: Execution of super class constructor(s),
*which is again divided in three phases if implemented
super->constructor EXPORTING ….
*Phase-3: Attributes of superclass are correctly
*initialized, access to instance attributes only
………………………………………….
ENDMETHOD.

The methods of subclasses are not visible in constructors. If an instance constructor calls
an instance method of the same class via the implicit self-reference (me), the method is
called in the way in which it is implemented in the class of the instance constructor, and
not the possibly redefined method of the subclass to be instantiated.

Listing below shows the behavior of instance constructors in inheritance using a simple
example.

REPORT z_oop_inhrt_constuctr.

CLASS lcl_vessel DEFINITION.


PUBLIC SECTION.
METHODS constructor IMPORTING
iname TYPE string.
PROTECTED SECTION.

247
DATA name TYPE string.
ENDCLASS. "lcl_vessel DEFINITION

CLASS lcl_vessel IMPLEMENTATION.


METHOD constructor.
name = iname.
WRITE: / 'lcl_vessel:constructor, name=',
name.
ENDMETHOD. "constructor
ENDCLASS. "lcl_vessel IMPLEMENTATION

CLASS lcl_ship DEFINITION


INHERITING FROM lcl_vessel.
ENDCLASS. "lcl_ship DEFINTION

CLASS lcl_motorship DEFINITION


INHERITING FROM lcl_ship.
PUBLIC SECTION.
METHODS constructor IMPORTING
iname TYPE string
ifuelamount TYPE i.
PRIVATE SECTION.
DATA fuelamount TYPE i.
ENDCLASS. "lcl_motorship DEFINITIO

CLASS lcl_motorship IMPLEMENTATION.


METHOD constructor.
super->constructor( iname ).
fuelamount = ifuelamount.
WRITE: / 'lcl_motorship:constructor, name ',
name, ' fuelamount ', fuelamount.
ENDMETHOD. "constructor
ENDCLASS. "lcl_motorship IMPLEMENTATION

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS. "lcl_example DEFINITION

CLASS lcl_example IMPLEMENTATION.


METHOD main.
DATA:
obj_vessel TYPE REF TO lcl_vessel,
obj_ship TYPE REF TO lcl_ship,
obj_motoship TYPE REF TO lcl_motorship.

WRITE 'Creating Vessel Object' COLOR 5.


SKIP.

CREATE OBJECT obj_vessel EXPORTING


iname = 'Ghata Khistay'.

248
WRITE / 'Creating Ship Object' COLOR 5.
SKIP.

CREATE OBJECT obj_ship EXPORTING


iname = 'Khistay'.

WRITE / 'Creating Motoship Object' COLOR 5.


SKIP.

CREATE OBJECT obj_motoship EXPORTING


iname = 'Rakotay Khistay'
ifuelamount = 400.
ENDMETHOD. "main
ENDCLASS. "lcl_example IMPLEMENTATION

START-OF-SELECTION.
lcl_example=>main( ).

Following is the output of the above example.

Static Constructors

Every class has a static constructor named class_constructor. Along an


inheritance tree the same rules that apply to the instance constructor also apply to the
static constructor.

When a subclass is addressed for the first time in a program, its static constructor is run.
Before that, however, the preceding static constructors of the entire inheritance tree must
have been run. Because a static constructor should be called only once during the
execution of a program, when a subclass is addressed for the first time, the next higher
superclass is searched whose static constructor has not yet run. Then this static

249
constructor is executed first, followed by the constructors of all subclasses up to and
including the addressed subclass. In contrast to instance constructors, a static constructor
does not have to explicitly call the static constructor of its superclass. Instead, the runtime
environment automatically ensures that the static constructors are called in the correct
order. In a subclass, we can always assume that the static attributes of the superclasses
have been correctly initialized. Note that the static constructors are parameter less.

The previous example is repeated with the use of static constructors; note the difference
between the output of both examples.

REPORT z_oop_inhrt_constuctr_static.

CLASS lcl_vessel DEFINITION.


PUBLIC SECTION.
CLASS-METHODS class_constructor.
CLASS-DATA name TYPE string.
ENDCLASS. "lcl_vessel DEFINITION

CLASS lcl_vessel IMPLEMENTATION.


METHOD class_constructor.
name = 'Ghata Khistay'.
WRITE: / 'lcl_vessel:class_constructor, name=',
name.
ENDMETHOD. "constructor
ENDCLASS. "lcl_vessel IMPLEMENTATION

CLASS lcl_ship DEFINITION


INHERITING FROM lcl_vessel.
ENDCLASS. "lcl_ship DEFINTION

CLASS lcl_motorship DEFINITION


INHERITING FROM lcl_ship.
PUBLIC SECTION.
CLASS-METHODS class_constructor.
CLASS-DATA fuelamount TYPE i.
ENDCLASS. "lcl_motorship DEFINITIO

CLASS lcl_motorship IMPLEMENTATION.


METHOD class_constructor.
name = 'Rakotay Khistay'.
fuelamount = 100.
WRITE: / 'lcl_motorship:class_constructor, name= ',
name, ', fuelamount ', fuelamount.
ENDMETHOD. "constructor
ENDCLASS. "lcl_motorship IMPLEMENTATION

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS. "lcl_example DEFINITION

250
CLASS lcl_example IMPLEMENTATION.
METHOD main.
DATA:
obj_vessel TYPE REF TO lcl_vessel,
obj_ship TYPE REF TO lcl_ship,
obj_motorship TYPE REF TO lcl_motorship.

WRITE 'Vessel Class' COLOR 5.


SKIP.
CREATE OBJECT obj_vessel.

WRITE / 'Ship Class' COLOR 5.


SKIP.
CREATE OBJECT obj_ship.

WRITE / 'Motoship Class' COLOR 5.


SKIP.
CREATE OBJECT obj_motorship.

ENDMETHOD. "main
ENDCLASS. "lcl_example IMPLEMENTATION

START-OF-SELECTION.
lcl_example=>main( ).

Following is the output.

Instantiation in Inheritance
The instantiation of subclass means the instantiation of all superclasses in a single object,
where the initialization of the superclass attributes is ensured by calling the superclass
constructors.

The additions CREATE PUBLIC|PROTECTED|PRIVATE of the CLASS statement or


the corresponding Class Builder settings, respectively, control for each class who can
create an instance of the class or call its instance constructor. In inheritance, this results in
three scenarios whose behavior is defined in ABAP Objects as follows:

251
• Superclass with Public Instantiation: The instance constructor of the superclass
is publicaly visible. If the instantiatiability of a subclass can be explicitly
specified in one of the three ways. A subclass can control the visibility of its own
instance constructor independently of the superclass.
• Superclass with Protected Instantiation: The instance constructor of the
superclass is visible in subclasses. If the instantiatiability of a subclass is not
explicitly it inherits the protected instantiation of the superclass. The
instantiatiability of a subclass can be explicitly specified in one of three ways. A
subclass can control the visibility of its own instance constructor independently of
the superclass and can thus also publish the protected instance constructor of the
superclass in the specified section.
• Superclass with Private Instantiation: The instance constructor of the superclass
is visible only in the superclass. There are two different scenarios here:
o The subclass is not a friend of the superclass; because only the superclass
itself can call its instance constructor, the subclass cannot be instantiated.
Therefore, the subclass has an implicit addition, CREATE NONE. The
instantiatiability if the subclass cannot be explicitly specified because this
would mean a publication oft the superclass constructor in the specified
section.
o The subclass is a friend of the superclass; if the instantiatiability of the
subclass has not been explicitly specified, it inherits the private
instantiation of the superclass. The instantiatiability of a subclass can be
explicitly specified in one of the three ways. As a friend, a subclass can
publish the private constructor of the superclass in the specified section.

If a superclass with private instantiation has been defined in a path of the inheritance tree,
no subclass can be instantiated by external users, and a subclass can’t even instantiate
itself because it doesn’t have access to the instance constructor of the superclass. Thus, a
class defined for private instantiation should be marked final to prevent subclasses.
Exception from this rule only exist if a privately instantiatable superclass offers its
friendship to its subclasses.

252
Interfaces
Interfaces or standalone interfaces are like a 100% abstract superclass that defines the
methods a subclass must implement. Methods of interface are all abstract. Like the
subclasses that implement the abstract methods of their abstract superclasses, all classes
that want to use an interface must implement its methods. With the exception, that we can
also define static methods without implementation, which is not possible in abstract
classes because static methods can not be redefined.

We can not directly create objects of interfaces similar to abstract classes. If a class
implements a standalone interface, it can be addressed via this interface. There are
specific interface reference variables for this purpose. These can point to objects of all
classes that contain the respective standalone interface. Because, any classes can
implement the same interface, their objects can be addressed via the same interface
reference variable.

Interfaces are used to achieve a decoupling between a class and a user. A very nice
application example of this decoupling is given by the enhancebility of delivered ABAP
application programs in customer systems using Business Add-Ins (BAdIs). BAdIs are
based on standalone interfaces that are declared in the original system. The actual
functionality of a BAdI is provided only in follow-up systems by implementing the
standalone interface in classes.

Creating Interfaces

The declaration of interfaces hardly varies from the declaration of a class. As with
classes, we distinguish global and local interfaces in the same way that we do global and
local classes. Therefore, the same rules apply regarding their usability. Global interfaces
can be used in any program if the package assignment of the program permits it. Local
interfaces can only be used in the same program. The syntax for declaring a local
interface is:

INTERFACE lif_name.
DATA ….
CLASS-DATA ...
METHODS ...
CLASS-METHODS ...
.................
ENDINTERFACE.

Interface can contain exactly the same components as classes. Unlike classes, however,
interfaces don’t need to be divided into different visibility sections because interface
components has by default public visibility. The local interface should be prefixed with
lif_ .

253
To create a global interface, use the Class Builder just as we would for global classes.
The global interface should be prefixed with if_ . Figure below shows the Class Builder
for a global interface. To create components we need to specify the same input as we do
for classes, except for the assignment to a visibility section. In the shown screenshot, we
created the methods ACCELERATE and SHOW_SPPED.

The Method Type specifies whether the method is a normal method, an event handler, a
constructor, etc. The Class Builder generates the corresponding ABAP statements in an
interface pool. An interface pool is a container for exactly one global interface; it cannot
contain any local type declarations except for the publication of type groups, the source
code of which can also be edited directly via GotoInterface Section.

254
There is no implementation part of an interface Therefore, it is not necessary to add the
DEFINITION to INTERFACE. The character (!) is escape character that can be written
directly before a name in order to distinguish it from an ABAP keyword of the same
name in a statement.

Implementing Interfaces

A class can implement one or more interfaces. The essential requirement for
implementing an interface is that the interface is known to the implementing class.
Therefore, it must be declared globally in the class library or locally in the same program.
Additionally, the usage of the interface must be permitted by the package assignment.
The syntax for integrating the interface is:

CLASS lcl_my_class DEFINITION.


PUBLIC SECTION.
INTERFACES: intf1, intf2 ...
……………………………….
…………………….
ENDCLASS.

Only global interfaces can be integrated in the public visibility section of a class. In Class
Builder we can do this on the Interfaces tab in the Change Class window.

255
In the Abstract and Final columns, we can specify that all methods of the interface should
be either abstract or final in the class. In the INTERFACES statement, this is expressed
by the optional addition ALL METHODS ABSTRACT|FINAL.

Implementing an interface extends the public interface (section) of the class by the
interface components. Every component comp of an implemented interface intf
becomes a full component of the class and is identified within the class via the name

… intf~comp …

The tilde sign (~) is the interface component selector. The prefix intf~ is helpful in
avoiding the naming conflicts when a class has its own component of the same name like
an interface component.

We might be tempted to address, the interface components of an object obj as follows:

obj->intf~comp.

In point of fact, this work, however, this kind of access is not recommended. The
interface component selector should only be used within classes and interfaces.

To access the interface components of objects, we must use the reference variables that
are declared with a reference to an interface:

DATA intf_ref TYPE REF TO lif_interf.

An interface reference variable intf_ref can point to the objects of all classes
implementing the lif_interf interface. The interface reference variable only knows
its own interface components. Other components (class specific components or
components of other interfaces) can not be addressed via an interface reference variable
instead class reference variable should be used to address the non-interface components
of the class.

By simply assigning a class reference variable (pointing to an object) to an interface


reference variable enable us to access the interface components. This mechanism is
known as upcast.

intf_ref = lcl_cls.

If we are only interested in the interface components of a class, we can create the object
of the class via an interface reference variable as:

CREATE OBJECT intf_ref TYPE lcl_cls.

Example below demonstrates the usage of interface reference variables.

256
REPORT z_interface01.

INTERFACE lif_drive_object.
METHODS: accelerate IMPORTING
idelta TYPE i,
show_speed.
ENDINTERFACE. "lif_drive_object

CLASS lcl_vehicle DEFINITION.


PUBLIC SECTION.
INTERFACES: lif_drive_object.
PRIVATE SECTION.
DATA speed TYPE i.
ENDCLASS. "lcl_vehicle DEFINITION

CLASS lcl_vehicle IMPLEMENTATION.


METHOD lif_drive_object~accelerate.
speed = speed + idelta.
ENDMETHOD. "lif_drive_object~accelerate
METHOD lif_drive_object~show_speed.
DATA msg TYPE string.
msg = speed.
CONCATENATE 'Vehicle Speed: ' msg INTO msg.
WRITE / msg.
ENDMETHOD. "lif_drive_object~show_speed
ENDCLASS. "lcl_vehicle IMPLEMENTATION

CLASS lcl_electron DEFINITION.


PUBLIC SECTION.
INTERFACES: lif_drive_object.
PRIVATE SECTION.
CONSTANTS c TYPE i VALUE 300000.
DATA speed_over_c TYPE p DECIMALS 3.
ENDCLASS. "lcl_electron DEFINITION

CLASS lcl_electron IMPLEMENTATION.


METHOD lif_drive_object~accelerate.
me->speed_over_c = me->speed_over_c + idelta / c.
ENDMETHOD. "lif_drive_object~accelerate
METHOD lif_drive_object~show_speed.
DATA msg TYPE string.
msg = me->speed_over_c.
CONCATENATE 'Electron Speed/C: ' msg INTO msg.
WRITE / msg.
ENDMETHOD. "lif_drive_object~show_speed
ENDCLASS. "lcl_electron IMPLEMENTATION

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
PRIVATE SECTION.

257
TYPES tab_intref TYPE TABLE OF REF TO lif_drive_object.
CLASS-METHODS show_msg IMPORTING
itab_iref TYPE tab_intref.
ENDCLASS. "lcl_example DEFINITION

CLASS lcl_example IMPLEMENTATION.


METHOD show_msg.
DATA irf LIKE LINE OF itab_iref.
LOOP AT itab_iref INTO irf.
irf->show_speed( ).
SKIP.
ENDLOOP.
ENDMETHOD. "msg
METHOD main.
DATA: if_tab TYPE tab_intref,
iref LIKE LINE OF if_tab,
veh_ref TYPE REF TO lcl_vehicle.

CREATE OBJECT veh_ref TYPE lcl_vehicle.


"upcaseting
iref = veh_ref.
iref->accelerate( 100 ).
APPEND iref TO if_tab.

CREATE OBJECT iref TYPE lcl_electron.


iref->accelerate( 250000 ).
APPEND iref TO if_tab.

lcl_example=>show_msg( if_tab ).
ENDMETHOD. "lcl_example
ENDCLASS. "lcl_example IMPLEMENTATION

START-OF-SELECTION.
lcl_example=>main( ).

The output of the above code listing is shown below:

258
As far as the static components of interface are concerned, we can only use the interface
name to access the constants.

intf =>const_attr.

The static attributes have different values depending on the class and the static methods
can be differently implemented in every class. To access the static components of
interfaces, independently of the instance, we would have to use the name of an
implementing class and the interface component selector:

class_name=>intf~comp.

Example below demonstrates the constants declared in an interface.

REPORT z_interface02.

INTERFACE lif_f1.
CONSTANTS att TYPE string VALUE 'Constant attribute of interfac
e'.
ENDINTERFACE. "if_f1

CLASS lcl_c1 DEFINITION.


PUBLIC SECTION.
interfaces: lif_f1.
ENDCLASS. "lcl_c1 DEFINITION

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS. "lcl_example DEFINITION

CLASS lcl_example IMPLEMENTATION.


METHOD main.
WRITE lif_f1=>att.
SKIP.
WRITE lcl_c1=>lif_f1~att.
ENDMETHOD. "main
ENDCLASS. "lcl_example IMPLEMENTATION

START-OF-SELECTION.
lcl_example=>main( ).

Following is the output of the above example.

259
Composite and Component Interfaces

The INTERFACES statement cannot only be used in classes but also in the declaration of
an interface. This mechanism allows us to compose several interfaces into one interface.
The composition of interfaces can be useful when modeling complex applications.
Following is the syntax:

INTERFACE lif_name.
INTERFACES: intrface1, interface2, …
…………………………………………
ENDINTERFACE.

Now the interface lif_name integrates additional interfaces (interface1,


interface2, …) and are composed of its own components plus the components of the
integrated interfaces.

In Class Builder we can compose other interface on the Interfaces tab.

An interface containing at least one other interface is called composite or nested


interface. An interface integrated in another interface is called a component interface.

Note: All component interface of a composite interface are on the same level. A nesting
of names like intterface3~interface2~interface2 is not possible.

Consider the example:

INTERFACE lif_interface1.
………………
ENDINTERFACE.

INTERFACE lif_interface2.
INTERFACES: lif_interface1 …
……..
ENDINTERFACE.

INTERFACE lif_interface3.
INTERFACES: lif_interface1, lif_interface2 …
……...

260
ENDINTERFACE.

In the example above the component interface lif_interface1 of the composite


interface lif_interface2 becomes a component interface of lif_interface3.
A composite interface contains each component interface exactly once. Although
lif_interface1 is integrated in lif_interface3 both directly as a component
interface of lif_interface3 and indirectly via lif_interface2, it only occurs
once. In lif_interface3, it can be addressed under the name lif_interface1,
even if it was not integrated directly.

If a composite interface is implemented in a class, all interface components of the


interface behave as if their interface had been implemented only once. Because every
interface is included exactly once in a composite interface, naming conflicts cannot
occur. The way an implemented interface is composed is irrelevant when it is
implemented in a class. Consider the next example:

INTERFACE lif_interface1.
METHODS meth.
ENDINTERFACE.

INTERFACE lif_interface2.
INTERFACES lif_interface1.
METHODS meth.
ENDINTERFACE.

INTERFACE lif_interface3.
INTERFACES lif_interface1.
METHODS meth.
ENDINTERFACE.

INTERFACE lif_interface4.
INTERFACES: lif_interface2, lif_interface3.
ENDINTERFACE.

CLASS lcl_demo DEFINITION.


PUBLIC SECTION.
INTERFACES lif_interface4.
ENDCLASS.

CLASS lcl_demo IMPLEMENTATION.


METHOD lif_interface1~meth.
.......
ENDMETHOD.
METHOD lif_interface2~meth.
.......
ENDMETHOD.
METHOD lif_interface3~meth.

261
.......
ENDMETHOD.
ENDCLASS.

A method meth of the same name is declared in three individual interfaces and thus
implemented in three different ways using the interface component selector. The
composition of the interfaces does not play any role. The lif_interface~meth
method is implemented only once, although it occurs in two interfaces,
lif_interface2 and lif_interface3. If we list one or more of other interfaces
(lif_interface1, lif_interface2 or lif_interface3) in addition to
lif_interface4 in the declaration part of the lcl_demo, the components and the
implementation part of the class do not change at all, because the compiler always
ensures for a class as well as in composite interfaces that every component exists only
once.

If the class implements a composite interface, the interface components should be


accessed using interface reference variable of the type of the appropriate component
interface. This can be achieved through upcasting. The interface component selector
should not be used for this purpose; however, it can be used in a composite interface to
make the components of component interfaces as accessible as native components via
aliasing.

Alias Names

The complete name of a component that is added via an interface to a class or another
interface is intf~comp. For this name, we can define an alias name at the level at
which the interface is integrated using the INTERFACES statement:

ALIASES name FOR intf~comp.

Alias names can be assigned when interfaces are implemented in the declaration part of a
class or when interfaces are composed in the declaration of an interface. In the Class
Builder we can enter alias names for classes and for interfaces in the Aliases tab.

262
In classes, alias names belong to the namespace of the components of a class and must be
assigned to a visibility section just like the other components. The visibility of an alias
name from outside the class depends on its visibility section and not on the visibility
section of the assigned interface component.

Listing below shows the usage of alias names.

REPORT z_interface03.

INTERFACE lif_drive_object.
METHODS: accelerate IMPORTING
idelta TYPE i,
show_speed.
ENDINTERFACE. "lif_drive_object

CLASS lcl_vehicle DEFINITION.


PUBLIC SECTION.
INTERFACES: lif_drive_object.
PRIVATE SECTION.
DATA speed TYPE i.
ENDCLASS. "lcl_vehicle DEFINITION

CLASS lcl_vehicle IMPLEMENTATION.


METHOD lif_drive_object~accelerate.
speed = speed + idelta.
ENDMETHOD. "lif_drive_object~accelerate
METHOD lif_drive_object~show_speed.
DATA msg TYPE string.
msg = speed.
CONCATENATE 'Vehicle Speed: ' msg INTO msg.
WRITE / msg.
ENDMETHOD. "lif_drive_object~show_speed
ENDCLASS. "lcl_vehicle IMPLEMENTATION

CLASS lcl_electron DEFINITION.


PUBLIC SECTION.
INTERFACES: lif_drive_object.
ALIASES accelerate FOR lif_drive_object~accelerate.
PRIVATE SECTION.
CONSTANTS c TYPE i VALUE 300000.
DATA speed_over_c TYPE p DECIMALS 3.
ENDCLASS. "lcl_electron DEFINITION

CLASS lcl_electron IMPLEMENTATION.


"instead of
"METHOD lif_drive_object~accelerate.
METHOD accelerate.
me->speed_over_c = me->speed_over_c + idelta / c.
ENDMETHOD. "lif_drive_object~accelerate
METHOD lif_drive_object~show_speed.
DATA msg TYPE string.

263
msg = me->speed_over_c.
CONCATENATE 'Electron Speed/C: ' msg INTO msg.
WRITE / msg.
ENDMETHOD. "lif_drive_object~show_speed
ENDCLASS. "lcl_electron IMPLEMENTATION

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
PRIVATE SECTION.
TYPES tab_intref TYPE TABLE OF REF TO lif_drive_object.
CLASS-METHODS show_msg IMPORTING
itab_iref TYPE tab_intref.
ENDCLASS. "lcl_example DEFINITION

CLASS lcl_example IMPLEMENTATION.


METHOD show_msg.
DATA irf LIKE LINE OF itab_iref.
LOOP AT itab_iref INTO irf.
irf->show_speed( ).
SKIP.
ENDLOOP.
ENDMETHOD. "msg
METHOD main.
DATA: irf_tab TYPE tab_intref,
irf_ref LIKE LINE OF irf_tab,
veh_ref TYPE REF TO lcl_vehicle,
ele_ref TYPE REF TO lcl_electron.

CREATE OBJECT veh_ref.


irf_ref = veh_ref.
irf_ref->accelerate( 100 ).
APPEND irf_ref TO irf_tab.

create OBJECT ele_ref.


irf_ref = ele_ref.
irf_ref->accelerate( 200 ).
APPEND irf_ref to irf_tab.

lcl_example=>show_msg( irf_tab ).
ENDMETHOD. "lcl_example
ENDCLASS. "lcl_example IMPLEMENTATION

START-OF-SELECTION.
lcl_example=>main( ).

The interface method is implemented in the class via its alias name and called by a user
like a direct method of the class. Thus using alias names, a class can publish its interface
components as class-specific components. Following is the output of the above code
listing.

264
Note, because names can not be concatenated in composite interfaces, alias names
provide the only means of addressing those components that would otherwise not be
available in the composite interface. For example:

INTERFACE intf1.
METHODS meth1.
ENDINTERFACE.

INTERFACE intf2.
INTERFACES intf1.
ALIASES meth1 FOR intf1~meth1.
ENDINTERFACE.

INTERFACE intf3.
INTERFACES intf2.
ALIASES meth1 FOR intf2~meth1.
ENDINTERFACE.

The intf3 interface can use the alias name meth1 in intf2 to address the meth1
component of the intf1 interface in its own ALIASES statement. Without alias
names in intf2, this would not be possible because the name intf2~intf1~m1 is
not permitted. Now the user of intf3 can accesses the component meth1 in intf1
as:

iref->meth1( ).

Without alias names in intf3, the access would look as follows:

iref->intf1~meth1( ).

Interfaces and Inheritance

The usage of inheritance always makes sense when different classes have
generalization/specialization relationship. The advantage of inheritance is that the
subclasses reuse all properties already programmed in the superclass, but at the same
time, this causes a very tight coupling (dependency) between superclass and subclasses.

265
That is a subclass strongly depends on its superclass. Every change to non-private
components of a superclass changes all of its subclasses. As a software engineering
principle we must follow the loose coupling or decoupling rule.

The interfaces or stand alone interfaces can be used to achieve the loose coupling.
Interfaces allow the user to handle the most different classes, which don’t need to be
related to each other. In OO modeling, interfaces provide an abstraction that is
independent of classes. Irrespective of the actual implementation, the services required by
a user can be described. Additionally, interfaces also implement an aspect of multiple
inheritance because several interfaces can be implemented in the class. In interface
multiple inheritance, the diamond problem (A method that is declared in a superclass is
redefined in two subclasses, which, in turn, make up the superclass of another subclass,
which implementation is used in this subclass?) does not occur, because in the
implementation of composite interfaces every interface method exists only once.

266
Polymorphism
The term polymorphism literally means “many forms”. From an object-oriented
perspective, the term is used to describe a language feature that allows you to use
instances of classes belonging to the same inheritance hierarchy interchangeably.

In a polymorphic design, we can create generic methods. This generic approach to


programming is often described using the term design by interface. The basic concept
here is to adopt a component-based architecture where each component clearly defines
the services (i.e. interface) they provide. These interfaces make it easy for components to
be weaved together into larger assemblies. Here, notice that we haven’t said anything
about how these components are implemented. As long as the components implement the
services described in their interface – it really doesn’t matter how they are implemented.
From an object-oriented perspective, this means that we can swap out a given object for
another so long as they share the same interface. In order to do so, we need to be able to
perform type casts and dynamic method calls.

Type Casting and Dynamic Binding


Most of the time, whenever we talk about the type of an object reference variable in
ABAP Objects, we are talking about its static type. The static type of an object reference
variable is the type that is specified after the TYPE REF TO addition in declaration as:

DATA obj_ref TYPE REF TO class|interface.

The static type is fixed during entire runtime of the program. An object reference variable
also has a dynamic type associated with it. The dynamic type of an object reference
variable is the class of the object to which the object reference variable is currently
pointing. The reference variable usually receives its dynamic type via assignment,
parameter transfers or via CREATE OBJECT statement as:

CREATE OBJECT obj_ref TYPE class.

Normally, the static and dynamic type of an object reference variable will be the same as:

CREATE OBJECT obj_ref.

Here dynamic type will be similar to static type of obj_ref. However, it is technically
possible for an object reference variable to point to an object that is not an instance of the
class type used to define the object reference. According to the golden rule of reference
variables, “The static type always more general or equal to the dynamic type”. The syntax
check and the ABAP runtime environment ensure that this rule is never broken. The
actual meaning of the golden rule for the two possible types of reference variables in
ABAP Objects is:

267
• For a class reference variable, the static type is a class; the dynamic type can be
the same class or one of its subclasses.
• For an interface variable, the static type is an interface. The dynamic type can be
any class implementing the interface, particularly even a subclass of such a class.

For example, notice how we are assigning an instance of the lcl_lion subclass to the
ref_animal object reference variable (whose static type is the parent class
lcl_animal) in the code excerpt below.

DATA: ref_animal TYPE REF TO lcl_animal,


ref_lion TYPE REF TO lcl_lion.

CREATE OBJECT ref_animal.


CREATE OBJECT ref_lion.

ref_animal = ref_lion.

This kind of assignment is not possible without a type cast. We can’t perform a type cast
using just any class; the source and target object reference variables must be compatible
(e.g., their static types must belong to the same inheritance hierarchy). In the example
above, once the assignment is completed, the dynamic type of the ref_animal
reference variable will be the lcl_lion class. Therefore, at runtime, when a method
call such as “ref_animal->hungry( )” is called, the ABAP runtime environment
will use the dynamic type information to bind the method call with the implementation
provided in the lcl_lion class.

The type cast above is classified as a narrowing cast (or upcast) as we are narrowing the
access scope of the referenced lcl_lion object to the components defined in the
lcl_animal superclass. In upcast we only assign more specific reference variables
(e.g. subclass) to equal or more general (e.g. superclass) ones and thus we can only move
upwards in the inheritance tree. An up cast assignment can be performed using the equal
sign (=) or the MOVE TO statement.

The opposite of narrowing cast is widening cast (or downcast) likes this:

DATA: ref_animal TYPE REF TO lcl_animal,


ref_lion TYPE REF TO lcl_lion.

CREATE OBJECT ref_animal TYPE lcl_lion.

ref_lion ?= ref_animal.

In this case, we are using the TYPE addition to the CREATE OBJECT statement to
create an instance of class lcl_lion and assign its reference to the ref_lion object

268
reference variable. Then, we use the casting operator (?= or ?TO in case of MOVE) to
perform a widening cast when we assign the ref_animal object reference to
ref_lion. The question mark explicitly shifts the checking of the golden rule from the
syntax check to the program runtime. The assignment is only executed if the golden rule
is then fulfilled for the target variable; otherwise, the exception
CX_SY_MOVE_CAST_ERROR is caused, which can be handed in a TRY control
structure. In downcast a more general reference variable (e.g. superclass) is assigned to a
more specific reference variable (e.g. superclass) and we thus move downward in the
inheritance tree.

Listing below shows an example of up cast and down cast in inheritance.

REPORT z_inherit_down_up_cast01.

CLASS lcl_animal DEFINITION.


PUBLIC SECTION.
METHODS: hungry.
ENDCLASS. "lcl_animal DEFINITION

CLASS lcl_lion DEFINITION


INHERITING FROM lcl_animal.
PUBLIC SECTION.
METHODS: hungry REDEFINITION,
fasting.
ENDCLASS. "lcl_lion DEFINITION

CLASS lcl_animal IMPLEMENTATION.


METHOD hungry.
WRITE: / 'An animal is hungry'.
ENDMETHOD. "hungry
ENDCLASS. "lcl_animal IMPLEMENTATION

CLASS lcl_lion IMPLEMENTATION.


METHOD hungry.
WRITE: / 'A Lion (King of Jungle) is hungry.',
' Run as fast as you can..!' .
ULINE AT /28(6).
ENDMETHOD. "hungry
METHOD fasting.
WRITE: / 'Stop running. Lion is on', 'Fasting today.'.
ULINE AT /26(7).
ENDMETHOD. "fasting
ENDCLASS. "lcl_lion IMPLEMENTATION

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS. "lcl_example DEFINITION

CLASS lcl_example IMPLEMENTATION.

269
METHOD main.
DATA: ref_animal TYPE REF TO lcl_animal,
ref_lion TYPE REF TO lcl_lion,
ref_lion_temp TYPE REF TO lcl_lion,
ref_cast_error TYPE REF TO cx_sy_move_cast_error.

"upcast (subclass is assigned to superclass)


CREATE OBJECT ref_lion_temp.
ref_animal = ref_lion_temp.

"downcast (superclass is assigned to subclass)


"with setting up the proper object reference in the Super ref
erence
TRY.
ref_lion ?= ref_animal.

CATCH cx_sy_move_cast_error INTO ref_cast_error.


WRITE: / 'Down cast failed 1' COLOR = 6.
ENDTRY.

IF ref_lion IS NOT INITIAL.


CALL METHOD ref_lion->hungry( ).
SKIP.
CALL METHOD ref_lion->fasting( ).
ENDIF.

SKIP.

"downcast without setting up the proper object reference in


the Super reference
CLEAR: ref_animal,
ref_lion,
ref_cast_error.

CREATE OBJECT ref_animal.

TRY.
ref_lion ?= ref_animal.
CATCH cx_sy_move_cast_error INTO ref_cast_error.
WRITE: / 'Down cast failed 2' COLOR = 6.
ENDTRY.

IF ref_lion IS NOT INITIAL.


CALL METHOD ref_lion->hungry( ).
CALL METHOD ref_lion->fasting( ).
ENDIF.

ENDMETHOD. "main
ENDCLASS. "lcl_example IMPLEMENTATION

270
START-OF-SELECTION.
lcl_example=>main( ).

Following is the output of above code listing.

Listing below shows an example of the down cast when using the interfaces.

REPORT z_inherit_down_cast02.

INTERFACE lif_drive.
METHODS: accelerate IMPORTING
idelta TYPE i,
show_speed.
ENDINTERFACE.
CLASS lcl_electron DEFINITION.
PUBLIC SECTION.
INTERFACES: lif_drive,
if_serializable_object.
PRIVATE SECTION.
CONSTANTS c TYPE i VALUE 300000.
DATA speed_over_c TYPE p DECIMALS 3.
ENDCLASS. "lcl_electron DEFINITION

CLASS lcl_vehicle DEFINITION.


PUBLIC SECTION.
INTERFACES lif_drive.
PRIVATE SECTION.
DATA speed TYPE i.
ENDCLASS. "lcl_vehicle DEFINITION

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
PRIVATE SECTION.
TYPES iref_tab TYPE TABLE OF REF TO lif_drive.

CLASS-METHODS: msg IMPORTING


itab TYPE iref_tab,
serialize IMPORTING
iref TYPE REF TO lif_drive.

ENDCLASS. "lcl_example DEFINITION

271
CLASS lcl_electron IMPLEMENTATION.
METHOD lif_drive~accelerate.
me->speed_over_c = me->speed_over_c + idelta / c.
ENDMETHOD. "lif_drive~accelerate

METHOD lif_drive~show_speed.
DATA output TYPE string.
output = me->speed_over_c.
CONCATENATE 'Electron speed/c: ' output INTO output.
WRITE / output.
ENDMETHOD. "lif_drive~show_speed
ENDCLASS. "lcl_electron IMPLEMENTATION

CLASS lcl_vehicle IMPLEMENTATION.


METHOD lif_drive~accelerate.
speed = speed + idelta.
ENDMETHOD. "lif_drive_object~accelerate
METHOD lif_drive~show_speed.
DATA output TYPE string.
output = speed.
CONCATENATE 'Vehicle Speed: ' output INTO output.
WRITE / output.
ENDMETHOD. "lif_drive~show_speed
"lif_drive~accelerate
ENDCLASS. "lcl_vehicle IMPLEMENTATION

CLASS lcl_example IMPLEMENTATION.


METHOD main.
DATA: intrf_refs TYPE iref_tab,
iref LIKE LINE OF intrf_refs.

CREATE OBJECT iref TYPE lcl_vehicle.


iref->accelerate( 100 ).
APPEND iref TO intrf_refs.

CREATE OBJECT iref TYPE lcl_electron.


iref->accelerate( 250000 ).
APPEND iref TO intrf_refs.

lcl_example=>msg( intrf_refs ).
ENDMETHOD. "main

METHOD msg.
DATA iref LIKE LINE OF itab.
LOOP AT itab INTO iref.
iref->show_speed( ).
serialize( iref ).
ENDLOOP.
ENDMETHOD. "msg

272
METHOD serialize.
DATA: serl_ref TYPE REF TO if_serializable_object,
xml_str TYPE xstring.

TRY.

serl_ref ?= iref.

"Calls the specified XSLT/ST, XSLT of the repository


"XSLT/ST is programming language for describing transform
ations
"between ABAP data and XML formats.XSLT/ST programs are e
dited
"using the Transformation Editor (STRANS). First paramete
r is
"the transformation to use from the repository
CALL TRANSFORMATION id
SOURCE object = serl_ref
RESULT XML xml_str .

CATCH cx_sy_move_cast_error.
RETURN.
ENDTRY.
"The DISPLAY_XML_STRING function module of the repository
"displays the result of serialization in an HTML browser cont
rol
CALL FUNCTION 'DISPLAY_XML_STRING'
EXPORTING
xml_string = xml_str.
ENDMETHOD. "serialize
ENDCLASS. "lcl_example IMPLEMENTATION

START-OF-SELECTION.
lcl_example=>main( ).

The IF_SERIALIZABLE_OBJECT is a predefined tag interface. By integrating the tag


interface, classes or other interfaces stand out against the ABAP runtime environment. A
tag interface generally does not contain its own interface components, but instead assigns
a particular task to the integrating classes or interfaces and changes the way they are
handled by the ABAP Compiler. Once the IF_SERIALIZABLE_OBJECT is integrated in
the class, the attributes of that class object can serialized to XML using the
CALL TRANSFORMATION statement.

Before serialization takes place, the interface reference variable is checked if the
referenced object is serializable. This happens using the down cast.

Following is the output produced by the above code listing.

273
Implementing Polymorphism
The example code below defines an abstract base class called lcl_animal and two
concrete subclasses: lcl_cat and lcl_dog. In order to make the See-n-Say generic, we
define the interface of the “play()” method to receive an instance of class
lcl_animal. However, in the main method, you’ll notice that we create instances of
lcl_cat and lcl_dog and pass them to the See-n-Say. Here, we didn’t have to perform
an explicit type cast as narrowing type casts are performed implicitly in method calls.
Furthermore, since the lcl_cat and lcl_dog classes inherit the methods
“get_type()” and “speak()” from class lcl_animal, we can use instances of them
in the lcl_see_and_say generically.

274
REPORT z_polymorphism01.

CLASS lcl_animal DEFINITION ABSTRACT.


PUBLIC SECTION.
METHODS: get_type ABSTRACT,
speak ABSTRACT.
ENDCLASS. "lcl_animal DEFINITION

CLASS lcl_cat DEFINITION


INHERITING FROM lcl_animal.
PUBLIC SECTION.
METHODS: get_type REDEFINITION,
speak REDEFINITION.
ENDCLASS. "lcl_cat DEFINITIO

CLASS lcl_dog DEFINITION


INHERITING FROM lcl_animal.
PUBLIC SECTION.
METHODS: get_type REDEFINITION,
speak REDEFINITION.
ENDCLASS. "lcl_dog DEFINITIO

CLASS lcl_see_and_say DEFINITION.


PUBLIC SECTION.
CLASS-METHODS: play IMPORTING
im_animal TYPE REF TO lcl_animal.
ENDCLASS. "lcl_see_and_say DEFINITION

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS. "lcl_example DEFINITION

CLASS lcl_cat IMPLEMENTATION.


METHOD get_type.
WRITE: 'Cat'.
ENDMETHOD. "get_type

METHOD speak.
WRITE: 'Meow'.
ENDMETHOD. "speak
ENDCLASS. "lcl_cat IMPLEMENTATION

CLASS lcl_dog IMPLEMENTATION.


METHOD get_type.
WRITE: 'Dog'.
ENDMETHOD. "get_type

METHOD speak.
WRITE: 'Bark'.
ENDMETHOD. "speak

275
ENDCLASS. "lcl_dog IMPLEMENTATION

CLASS lcl_see_and_say IMPLEMENTATION.


METHOD play.
WRITE: 'The'.
CALL METHOD im_animal->get_type.
WRITE: 'says'.
CALL METHOD im_animal->speak.
ENDMETHOD. "play
ENDCLASS. "lcl_see_and_say IMPLEMENTATION

CLASS lcl_example IMPLEMENTATION.


METHOD main.
DATA: ref_cat TYPE REF TO lcl_cat,
ref_dog TYPE REF TO lcl_dog.

CREATE OBJECT ref_cat.


CREATE OBJECT ref_dog.

lcl_see_and_say=>play( EXPORTING
im_animal = ref_cat ).
NEW-LINE.
lcl_see_and_say=>play( EXPORTING
im_animal = ref_dog ).
ENDMETHOD. "main
ENDCLASS. "lcl_example IMPLEMENTATION

START-OF-SELECTION.
lcl_example=>main( ).

As mentioned earlier, one of the primary advantages of using polymorphism in a design


like this is that we can easily plug in additional animals without having to change
anything in class lcl_see_and_say. Following output is produced by executing the
above code.

276
The following example demonstrates the polymorphism using both interfaces and
abstract classes.

1. Create and activate the table zt_accounts as shown below:

2. To create and activate the global interface z_if_account open the Class Builder
(SE24) as shown below:

277
3. Create and activate the global abstract class z_cl_account as shown below:

278
4. Next to implement the methods of z_cl_account, double click each method to
write code for it, as show below:

279
5. The following concrete global class z_cl_checking_account specializes the
abstract z_cl_account as shown below:

280
6. The redefined withdraw method of concrete global class
z_cl_savings_account throws an exception when the account is overdrawn.

281
The following application program works with bank accounts in a very general way.

REPORT z_interface_banking.

CLASS lcl_account_management DEFINITION.


PUBLIC SECTION.

282
METHODS handle_debit_balance FOR EVENT
overdraw OF z_cl_checking_acc
ount
IMPORTING
id
amount.

ENDCLASS. "lcl_bank_management DEFINITION

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS: main,
withdraw IMPORTING
account TYPE REF TO z_if_account
amount TYPE ztaccounts-amount,
transfer IMPORTING
source TYPE REF TO z_if_account
target TYPE REF TO z_if_account
amount TYPE ztaccounts-amount.
ENDCLASS. "lcl_example DEFINITION

CLASS lcl_account_management IMPLEMENTATION.


METHOD handle_debit_balance.
DATA text TYPE string.
text = amount.
CONCATENATE `Handling debit ` text ` for account ` id INTO te
xt.
MESSAGE text TYPE 'I'.
ENDMETHOD. "handle_debit_balance
ENDCLASS. "lcl_bank_management IMPLEMENTATION

CLASS lcl_example IMPLEMENTATION.


METHOD withdraw.
DATA txt TYPE string.
TRY.
account->withdraw( amount ).
CATCH zcx_negative_amount.
txt = account->id.
CONCATENATE 'Withdrawal not possible from ' txt INTO txt.
MESSAGE txt TYPE 'I'.
ENDTRY.
ENDMETHOD. "withdraw

METHOD transfer.
DATA txt TYPE string.
TRY.
source->transfer( amount = amount
target = target ).
CATCH zcx_negative_amount.
txt = source->id.
CONCATENATE 'Transfer not possible from ' txt INTO txt.

283
MESSAGE txt TYPE 'I'.
ENDTRY.
ENDMETHOD. "transfer
METHOD main.
DATA: acc1 TYPE REF TO z_if_account,
acc2 TYPE REF TO z_if_account,
acc_handler TYPE REF TO zcl_account_management.

CREATE OBJECT: acc1 TYPE z_cl_checking_account


EXPORTING id = '0000815',
acc2 TYPE z_cl_savings_account
EXPORTING id = '0000415',
acc_handler.
"register the event handler
SET HANDLER acc_handler->handle_debit_balance
FOR ALL INSTANCES.

lcl_example=>withdraw( account = acc1


amount = 100 ).
lcl_example=>transfer( source = acc1
target = acc2
amount = 500 ).
lcl_example=>withdraw( account = acc2
amount = 1000 ).
lcl_example=>transfer( source = acc2
target = acc1
amount = 1000 ).
ENDMETHOD. "main
ENDCLASS. "lcl_example IMPLEMENTATION

START-OF-SELECTION.
lcl_example=>main( ).

Following is the output of above example.

284
Events and Event Handling
Events enable the objects of a class or a class itself to publish changes to its state, and
other objects and classes can then react to this change of state.

Before going deep into the details of events lets consider an example how events work.
Aboard an aircraft there are passengers, cabin crew and the pilots. The passenger and
pilots can press a button that calls a flight attendant. As soon as the event “button
pressed” occurs, the flight attendant determines who pressed the button and performs an
appropriate action.

In the above example we are dealing with three classes (passenger, pilot, and cabin crew).
The instances of the passenger, pilot classes are able to trigger events (button pressed) in
which the instances of class cabin crew take interest and react accordingly by executing
an appropriate method.

But events can not be implemented using normal direct method calls. As to call a normal
method, the address must be known and a called method must always react. But in the
above case; we don’t know which cabin crew instance is going to react to the button
pressed event (address of method not known) and the cabin crew instance can decided not
to acknowledge the button pressed event as they are ignored during take-off and landing
(method not always react).

However; triggering events is an indirect method call. The event concept established
through the Publish-and-Subscribe mechanism. This mechanism takes place on two
levels; i.e. statically at the time of declaration and dynamically at the time of program
execution.

The Publish-and Subscribe mechanism in ABAP Objects are implemented as follows:

285
• Events: A class can contain events as static or instance components. Every
method of that class can trigger those events.
• Event Handler: An event handler is a method of another class or the same class
that can handle an event, that is, that can be indirectly called by the event. The
role of a method as an event handler is statically specified during its declaration.
• Event Handler Registration: The handling of an event by a proper event handler
can be explicitly registered, without an appropriate registration, no handling takes
place.

Declaring Events
Events declaration is the static publishing of events in Publish-and-Subscribe mechanism.
Events can be declared in one of the three visibility sections of the class or in an
interface. The syntax for declaring instance and static events are:

[CLASS-] EVENTS event_name [EXPORTING … VALUE(param1) TYPE


type . . .].

Instance events can only be triggered in instance methods. Static events can be triggered
in instance and static methods. An event has an optional parameter interface that may
exclusively contain output parameters that are passed by value. This interface enables the
transfer of actual parameters to the formal parameters of event handlers when events are
triggered. The parameter interface of event handler is determined by the parameter
interface of the event.

Note; each instance event also has an implicit output parameter named sender. This
output parameter has the type of an object reference variable. After the event has been
triggered using the RAISE EVENT statement, sender points to the triggering object.

In Class Builder the events are declared on the Events tab as show in the figure below:

The parameter interface is declared as for methods, where the type of the parameter does
not have to be specified.

286
Triggering Events
The triggering of an event is the dynamic publishing in Publish-and-Subscribe
mechanism. In instance methods, we can trigger the instance events and the static events
of the corresponding class; in static methods, we can only trigger the static events. The
syntax for triggering an event is as follows:

RAISE EVENT event_name EXPORTING ... eparami = valuei ...

This statement interrupts the execution of the method and executes all event handlers
registered for the event in the order of their registration. Then the triggering method is
continued behind the RAISE EVENT statement. Events cal also be triggered during
event handling.

Using the EXPORTING addition, actual parameters must be attached to all non-optional
exporting parameters of the event. By doing so, the input parameters of the event
handlers are provided with values.

Event Handlers
Event handler declaration is the static subscription in Publish-and-Subscribe mechanism.
Every class can contain event handlers for the events of other classes or their own class.
Event handlers are methods that are specifically identified as such shown below:

[CLASS-]METHODS handler_name FOR EVENT event_name OF


class|interface IMPORTING … eparami … [sender].

The addition FOR EVENT makes a method an event handler and assigns it to exactly one
event of a class or an interface. The class or interface specified for the event
handler determines which objects or classes can trigger the execution of the event
handler. In an instance event, an event handler can be triggered by all objects, the classes
of which are equal to or more specific than class or that implements the interface
directly or via super class. For a static event, the same applies to the class.

The parameter interface of an event handler may exclusively contain input parameters
that were defined with the same names as output parameters when the event was
declared. An event handler does not need to take all parameters, with exception of the
implicit parameter sender.

In Class Builder the event handler can be defined in the Detail View of methods as shown
below:

287
Under the Parameters, only parameters of the event, including the predefined sender
parameter can be entered.

Registering Event Handlers


Event handler registration is the dynamic subscription in Publish-and-Subscribe
mechanism. For an event handler to react to a triggered event, it must be registered
accordingly at runtime. The registration couples event handlers to triggers. This coupling
can be dissolved at any time. The syntax for registering event handlers for instance event
is:

SET HANDLER handler1 handler2 … FOR obj_ref|[ALL INSTANCES]


[ACTIVATION act].

This statement registers the event handlers handler1, handler2, … for


corresponding instance events of the object to which the obj_ref reference variable
provided after FOR is pointing. The event handlers are specified like the methods of a
static method call. The static type of obj_ref is restricted by the specified event
handler. It must be more specific or equal to the class classes and implement all
interfaces that were used when declaring the individual event handlers. When
obj_ref is specified, event handlers are registered for the events of exactly one object.

Alternately, using ALL INSTANCES, event handlers can be registered for all objects,
the instance events of which they can handle. This registration also applies to all objects
that are not created until after the SET HANDLER statement.

288
In static events, the addition FOR is omitted and the registration is performed for all
classes and interfaces that can be handled by the specified handler. This means that in one
statement, either only instance events or only static events can be registered.

The addition ACTIVATION determines if the specified handlers are to be registered (X)
or deregistered (“ “), where registration is the default setting. Technically, every
registration is equal to a line in a invisible system table.

The following example demonstrates the use of event handling in detail.

REPORT z_event_handling.

CLASS lcl_pilot DEFINITION.


PUBLIC SECTION.
EVENTS button_pressed.
METHODS call_flight_attendent.
ENDCLASS. "lcl_pilot DEFINITION

CLASS lcl_passenger DEFINITION.


PUBLIC SECTION.
DATA cls TYPE string READ-ONLY.
METHODS constructor IMPORTING
iseat_no TYPE i
icls TYPE string.
EVENTS button_pressed EXPORTING
value(eseat_no) TYPE i.
METHODS call_flight_attendent.
PRIVATE SECTION.
DATA seat_no TYPE i.
ENDCLASS. "lcl_passenger DEFINITION

CLASS lcl_flight_attendent DEFINITION.


PUBLIC SECTION.
METHODS constructor IMPORTING
ititle TYPE string.
METHODS help_the_pilot
FOR EVENT button_pressed OF lcl_pilot.
METHODS help_the_passenger
FOR EVENT button_pressed OF lcl_passenger IMPORTING
eseat_no
sender.
PRIVATE SECTION.
DATA title TYPE string.
ENDCLASS. "lcl_flight_attendent DEFINITION

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS. "lcl_example DEFINITION

CLASS lcl_pilot IMPLEMENTATION.


METHOD call_flight_attendent.
RAISE EVENT button_pressed.
ENDMETHOD. "call_flight_attendent

289
ENDCLASS. "lcl_pilot IMPLEMENTATION

CLASS lcl_passenger IMPLEMENTATION.


METHOD constructor.
me->seat_no = iseat_no.
me->cls = icls.
ENDMETHOD. "constructor
METHOD call_flight_attendent.
RAISE EVENT button_pressed EXPORTING
eseat_no = me->seat_no.
ENDMETHOD. "call_flight_attendent
ENDCLASS. "lcl_pessenger IMPLEMENTATION

CLASS lcl_flight_attendent IMPLEMENTATION.


METHOD constructor.
me->title = ititle.
ENDMETHOD. "constructor
METHOD help_the_pilot.
DATA txt TYPE string.
CONCATENATE me->title ' helps pilot ' INTO txt RESPECTING BLANKS.
MESSAGE txt TYPE 'I'.
ENDMETHOD. "help_the_pilot
METHOD help_the_passenger.
DATA txt TYPE string.
txt = eseat_no.
CONCATENATE me->title ' helps ' sender->cls
' passenger on seat ' txt INTO txt RESPECTING BLANKS.
MESSAGE txt TYPE 'I'.
ENDMETHOD. "help_the_passenger
ENDCLASS. "lcl_flight_attendent IMPLEMENTATION

CLASS lcl_example IMPLEMENTATION.


METHOD main.
DATA:
pilot TYPE REF TO lcl_pilot,
passenger1 TYPE REF TO lcl_passenger,
passenger2 TYPE REF TO lcl_passenger,
attendent1 TYPE REF TO lcl_flight_attendent,
attendent2 TYPE REF TO lcl_flight_attendent.
CREATE OBJECT:
pilot,
passenger1 EXPORTING
iseat_no = 11
icls = 'Business Class',
passenger2 EXPORTING
iseat_no = 233
icls = 'Economy Class',
attendent1 EXPORTING
ititle = 'Komal',
attendent2 EXPORTING
ititle = 'Ayesha'.
SET HANDLER:
attendent1->help_the_pilot FOR pilot,
attendent2->help_the_passenger FOR ALL INSTANCES.

pilot->call_flight_attendent( ).

290
passenger1->call_flight_attendent( ).
passenger2->call_flight_attendent( ).
ENDMETHOD. "main
ENDCLASS. "lcl_example IMPLEMENTATION

START-OF-SELECTION.
lcl_example=>main( ).

Following is the output of the above code listing.

291
Shared Objects
The objects we dealt with so far reside in the internal session of an ABAP program. This
means these objects can be accessed only within an internal session. If we recall the topic
“Memory Organization of Application Server ABAP” we find that the only shared
memory of the application server is suitable for storing objects that can be accessed by all
of the programs of ABAP server. For frequent database access, AS ABAP includes an
implicit mechanism called SAP buffering, where the raw data from the database is
already buffered in the shared memory. For explicit and OO access to the shared
memory, shared objects have been introduced in SAP NetWeaver 2004.

Shared memory contains an area called Shared Objects Memory where objects can be
stored as shared objects. This includes both instances of classes and anonymous data
objects (data objects created with CREATE DATA statement). The following sections
introduce the programming interface for shared objects.

Areas
The management and access to the shared objects memory are performed via areas. The
shared objects memory is divided into area instances that can exist in different versions.
The actual shared objects are stored in the area instance versions.

An area is a repository object that describes the technical properties of area instances.
The term “area” in this context should not be confused with a memory area in the shared
object memory, which applies only to area instances. There can be several area instances
of an area. In simple terms, an area is just a collection of settings that describe the
properties of area instances, like versioning, lifetime and so forth.

For every area, a global area class of the same name is generated. However, this is not a
template for area instances but for area handles. An area handle is an object of an area
class whose methods can be used by ABAP programs to access the area instances of the
relevant area and thus the shared objects stored therein. Area calluses provide the only
possible means of access from ABAP programs to the shared objects memory.

292
To store objects as shared objects in area instances, their classes must be identified as
shared memory enabled as follows:

CLASS cls_name DEFINITION … SHARED MEMORY ENABLED.

In Class Builder, the Shared Memory-Enabled property must be selected as:

During definition, every area must be assigned a global shared memory-enabled class as
an area root class. An area instance where shared objects are stored must contain at least
one instance of the area root class as a root object. The root object can contain working
data itself and reference other shared objects (instances of shared memory-enabled
classes or data objects) of the area instance. An area handle has an attribute named ROOT
that can be used to address the root object.

Accessing Shared Objects


The access to shared objects is achieved via an area handle, that is, by means of an object
of an area class. The shared objects are stored in an area instance version in the shared
memory. The properties of area handle and area instance are specified by the
corresponding area in the ABAP Workbench. Figure below depicts the access to shared
objects.

293
The initial access from internal session to the shared objects of an area instance is always
achieved via the area handle ROOT reference variable pointing to the root object. The
figure above shows an area instance version with two shared objects, the root object and
another object. From an internal session, a reference to a shared object can only be used
as long as this session is connected to the area instance via an area handle, because this
handle provides the required lock of the area instance. The oref reference shown in this
figure should therefore be resolved for security reasons before the access via the area
handle is terminated. The same applies to references from shared objects to objects of the
internal session.

While an area instance version is attached to an internal session via an area handle, it can
be regarded as its extension. Area instance versions to which no area handles are attached
are ideally self-contained, that is, there should only be references within an area instance
version. The static attributes of a shared memory-enabled class are not treated differently
from those of a normal class.

Creating an Area
The ABAP Workbench includes the Area Management tool (TCode, SHMA) to create an
area. The creation of an area generates the area class of the same name. Therefore, the
area name should follow the naming conventions for global classes. Every area class
inherits from the predefined class CL_SHM_AREA, which, in turn, inherits from
CL_ABAP_MEMORY_AREA. Every area handle therefore contains a set of predefined
methods and attributes.

When an area is created, the area properties are set. These are divided into basic
properties, fixed, dynamic and runtime area properties.

Basic Properties

294
The basic properties of an area are considered when the area class is generated. When the
basic properties of an area are changed during operation, all area instance versions of the
area are set to expired and the area class is regenerated. The basic properties are:

• Area Name: The name of an area. This is also the name of the generated global
area class and is therefore unique across the system. It is recommended that you
follow the naming conventions for global classes in the current system, and use
the prefix “CL_“.
• Area Root Class: The area root class is a global shared memory-enabled class that
has to be assigned to an area when it is defined. The ROOT attribute of a
corresponding area handle is generated as a reference variable with the static type
of the area root class.
• Client Dependent Area: An area can be described as client-dependent. In this
case, an area instance of the area is identified by a client identifier as well as by its
name. With client-dependent areas, the area class methods refer to accessing an
area instance on the current client. With client-dependent areas, these methods
have an additional input parameter, CLIENT, which enables explicit access to
other clients.
• Area Build Type: If this property is set, a new area instance is created
automatically at the time selected in the area build type.
• Transactional Area: Transactional area enables data or objects in the area
instance versions to join such areas to database contents.

Fixed Properties

The fixed properties determine the context of an area and whether versioning takes place
as:

• Area Binding: This property determines the visibility and lifetime of the area
instance versions of the instance by specifying a context. Possible contexts are:
Application Server, Session, External Session, and ABAP Memory.
• Area Instance Versioning: This property defines whether there can be only one or
several area instance versions of an area instance. Without versioning, there is
only one version and the area instance is equivalent to this area instance version.

Dynamic Properties

The dynamic properties of an area are not considered when the area class is generated.
When the dynamic properties of an area are changed dynamically during operation, the
current area instance versions (versions that are being built, are active or are obsolete) are
not affected. The new dynamic properties are not used until the next change lock is set in
the corresponding version that is being built.

• Area Constructor Class: Any global class that implements the


IF_SHM_BUILD_INSTANCE interface can be specified as an area constructor

295
class. The implementation of the IF_SHM_BUILD_INSTANCE~BUILD
interface method is used as the area constructor.
• Displacement Type: This property determines whether and how instances of the
area can be displaced. Displacement may be necessary if the available addressing
area of the shared memory is not sufficient for all area instance versions. Possible
displacement types are: Displacement Not Possible, Displacement Possible with
Backup and Recovery and Displacement Possible.

Runtime Dependent Properties

The same points apply to runtime-dependent properties of an area as to dynamic area


properties, with the difference that they can only be given default values by a developer
and can also be changed without a developer key, for example by administrators, during
Customizing or during operation. Runtime dependent properties are: Area Build Type,
Area Size, Size of an Area Instance Version, Number of Versions of an Area Instance,
and Lifetime of an Area Instance.

As an example, we would create a simple area that can be used in applications working
with the flight data model.

296
The global class z_cl_flight_list contains an internal table flight_list of
the existing type spfli_tab from the ABAP Dictionary, which is filled by a
set_flight_list method. This table contains the unchangeable data that is to be
accessed from different programs.

Next open the Area Management tool (TCode, SHMA) to set properties for
z_cl_flights area as shown below:

297
We turned off the versioning because we are not planning to change the data in the area
instance at program runtime and restrict the lifetime. The restriction of the lifetime

298
prevents space in the shared memory from being consumed without actually being used
by the program.

Locking
The access to shared objects is controlled via locks. The locking concept of shared
objects is similar to that of a file system. This means that there are exclusive locks for
creating or changing shared objects in area instances, and read locks for accessing shared
objects.

• Read Lock: If a read lock is set for an area in program, the current area instance
version can be read. Within an internal session, there can be maximum of one
read lock for an area instance. Across several sessions, there can be several read
locks on an area instance versions.
• Write Lock: If a write lock is set for an area in a program, a new area instance
version can be created and can be populated with data.
• Update Lock: If an update lock is set for an area in a program, the data of the
current area instance version can be changed for areas without versioning. For
areas with versioning, a new are instance version is created that can then be
changed.

A change lock (write or update lock) locks an area instance version exclusively. Only
previous versions can be read-accessed in parallel. On AS there can be a maximum of
one change lock on an area instance. With versioning, a change lock can be set on an area
instance even if there are read locks. Without versioning, a change lock can only be set if
there is currently no read lock.

The locks are set when an internal session is attached to an area instance via an area
handle. A lock therefore always refers to all shared objects of an area instance. This
locking concept supports two application scenarios for shared objects:

• Usage as a Shared Buffer: A shared buffer contains a large amount of data that is
changed rarely (once a week up to once a day). In general, the data of a shared
buffer is provided once by a single program and many users read-access the
shared buffer simultaneously. A typical application of shared buffer is the storage
of a catalog or other stable lists.
• Usage as an Exclusive Buffer: An exclusive buffer contains data that is write- or
read-accessed by only one user across transaction boundaries. The data can be
created by the same user or another user. A typical application of an exclusive
buffer is the storage of a shopping cart that is first populated by the customer and
later read by the salesperson.

299
Working with Shared Objects
The shared objects memory is accessed via the methods and attributes of the area handle
that are partly inherited from the super classes CL_SHM_AREA and
CL_ABAP_MEMORY_AREA and partly generated when an area is created. To work with
area instances, the current internal session must be attached to them via an area handle.
This is achieved using the following static methods of the area class:

• ATTACH_FOR_READ: Creates a new area handle to the current area instance


version of an existing area instance and sets a read lock. Until the attachment is
removed, it is possible o read-access the attached are instance version in the
program.
• ATTACH_FOR_WRITE: Creates a new area instance version, attaches the area
handle to it, and sets a write lock. Until the attachment is removed, it is possible
to change access the new area instance version in the program. With versioning, a
new empty area instance version is created. Without versioning, the new area
instance version replaces a potential earlier area instance version.
• ATTACH_FOR_UPDATE: Attaches an area handle to an existing area instance
and sets an update lock. Until the attachment is dissolved, it is possible to change-
access the attached area instance version in the program. With versioning, a new
area instance version is created as a copy of the previous versions. Without
versioning, the area handle is attached to the current area instance version.

In the case of success, all methods return a reference to an area handle that holds one of
the three possible locks on the attached area instance version. If method is not successful,
because of no area instances or existing lock denies access, an exception is thrown that is
defined as a subclass of CX_SHM_ATTACH_ERROR.

To dissolved the connection, the DETACH instance method is used to detached the area
handle attached to an area instance version via a read lock while the DETACH_COMMIT
or DETACH_ROLLBACK instance methods can be used to detach the area handle attached
to an area instance version via a change lock. When disconnecting, the area instance
should be completed, that is, no reference may point from the internal session to a shared
object and vice versa.

Shared objects can be created from shared memory-enabled classes as follows:

CREATE OBJECT obj_ref AREA HANDLE area_handle …

Following the addition AREA HANDLE, we must specify a reference variable of the
static type of an area class that points to an area handle, which is attached to an area
instance version via a change lock.

The addition AREA HANDLE also exists for the CREATE DATA statement for creating
anonymous data objects.

300
If a change lock is detached using DETACH_COMMIT, an instance of the area root class
must be set as the root object of the area instance version. For this purpose, the
SET_ROOT instance method of the area handle must be called while the change lock is
set. The root object is the only shared object that can be addressed directly after attaching
an area handle to an area instance version.

It is recommended that we encapsulate the entire access to the shared memory in specific
classes and let an application program work only with these classes. Ideally, two classes
manage the accessing of shared objects:

• A loader creates and changes area instances.


• A broker takes care of the read access to area instances and can also contain the
necessary authorization checks (discussed in later chapters).

In the following program, we merged loader and broker into a single class.

301
Next implement the static constructor and methods as shown below:

In an internal session, there can only be one instance of class that is created in the static
constructor (Singleton). The get_flight_list method serves as a broker. It sets a
read lock on an area instance. Because there can be only one read lock on an area

302
instance within an internal session, it is always first queried whether there already is an
area handle. In case of a failure, the create_flight_list method is called that acts
as a loader. It tries to set a write lock and to build an area instance with a root object.
Potential exceptions are propagated to the calling method. Without explicitly removing
the change lock, there would be a program crash at the end of the current internal session
at the latest.

If the area built has been successful, get_fight_list tries to set another read lock. If
no area instance could be built, get_flight_list creates an object of the
z_cl_flight_list class in the current internal session and populates the internal
table flight_list. Lastly, the return value of the method is assigned a data reference
to the flight list, either in the root object of the shared object or in the local object.

Note that the write lock in create_flight_list is explicitly closed, while a read
lock in get_flight_list remains until the end of the internal session. In areas
without versioning, the latter is possible only if no change access are expected after an
area has been built.

The code in listing below shows an application program that works with the data from the
share object in the z_cl_flights area.

REPORT z_shared_objs.

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
PRIVATE SECTION.
CLASS-METHODS display IMPORTING
value(itable) TYPE ANY TABLE.
ENDCLASS. "lcl_example DEFINITION

CLASS lcl_example IMPLEMENTATION.


METHOD main.
DATA: flist_handler TYPE REF TO z_cl_flight_list_handler,
flist TYPE REF TO spfli_tab.

flist_handler = z_cl_flight_list_handler=>flight_list_handler.
TRY.
flist = flist_handler->get_flight_list( ).
CATCH zcx_no_flights.
MESSAGE 'No flight list available' TYPE 'I'
DISPLAY LIKE 'E'.
RETURN.
ENDTRY.
lcl_example=>display( flist->* ).
ENDMETHOD. "main
METHOD display.
"cl_salv_table is used for simple, two-dimensional table
DATA alv TYPE REF TO cl_salv_table.
TRY.
cl_salv_table=>factory( IMPORTING

303
r_salv_table = alv
CHANGING
t_table = itable ).
alv->display( ).
CATCH cx_salv_msg.
MESSAGE 'ALV display not possible' TYPE 'I'
DISPLAY LIKE 'E'.
ENDTRY.
ENDMETHOD. "display
ENDCLASS. "lcl_example IMPLEMENTATION

START-OF-SELECTION.
lcl_example=>main( ).

The object of z_cl_flight_list_handler is created, and then a reference to the


flight list is read. If the flight list was accessed successfully, it is output in the display
method using the ALV (SAP List Viewer). Following is the output of above application
program.

Shared Objects Management


Profile parameters specify how large the areas of the shared memory can become for
different requests like programs, program data, implicit buffers and the shared objects
memory. Shared memory is a valuable resource. In SAP Memory Management (TCode
ST02), the current memory consumption can be viewed.

In contrast to other requests to shared memory, the request for shared objects memory is
explicit. Therefore, a programmer must ensure that all unused memory is released. There
is a specific monitor for the shared objects memory. It can be called via TCode SHMM or

304
from SHMA. The monitor shows the properties of current area instances and also enables
change actions. Some of the functions of the shared objects monitor include:

• Display all area instances, their versions and the current locks.
• Display the contents of area instance versions.
• Display the memory consumption.
• Change the state of area instance versions (from active to obsolete).
• Delete the area instances.

If our previous program is run thrice in parallel within five minutes the display of the
shared objects monitor looks as shown in figure below:

The second area cl_icf_shm_area is used by the ABAP runtime environment.

305
Exception Handling
Exceptions are situations that occur while an ABAP program is being executed.
Exception situations can have different causes. Coding may actually be implemented
incorrectly. Another cause of exception situation is the interaction between a program
and external resources, such as user entries, the file system or the memory. Exception
situations can be detected by either the program or the runtime environment. When the
ABAP program or the runtime environment detects an exception situation, it triggers an
exception.

There are two main types of exceptions: those that can be handled (treatable) and those
that cannot be handled (untreatable).

• Treatable Exceptions: Exceptions that can be handled and where the program can
continue executing after the ABAP program has handled the exception, without
the system ending up in a critical state. If such an exception is not handled, a
runtime error occurs. Treatable exceptions are predefined in the system or can be
user defined.
• Untreatable Exceptions: Exceptions that cannot be handled. These are critical
error situations in the runtime environment. Handling is not possible and they
always cause a runtime error.

After a program has terminated with a runtime error, the system outputs a short dump that
contains the name of the runtime error, the related exception class, contents of data
objects, active calls and son on, and provides the option of navigating to the ABAP
Debugger. In the standard setup, short dumps are stored in the system for 14 days and
managed using transaction ST22.

In ABAP Objects we distinguish between class-based exceptions (since Release 6.10)


and classic exception handling.

Class Based Exception Handling


Class-based exception handling is based on exception classes. Exception classes can be
user defined or a series of predefined exception classes is also available. In an exception
situation, an exception is represented by an exception object, in other words, by an
instance of an exception class. System defined exceptions begin with prefix CX_SY_,
such as CX_SY_ZERODIVIDE. All exception classes must begin with the prefix CX_.
They are usually defined globally with the Class Builder of the ABAP Workbench. Local
exception classes can, however, also be defined.

Every exception class is derived directly or indirectly from the CX_ROOT superclass,
there are three other abstract exception classes for structuring possible exceptions. Figure
below shows all four classes and their relationships in the inheritance tree.

306
The key characteristics of the four classes are as follows:

• CX_ROOT: This is the super class from which every exception class is directly or
indirectly derived.
• CX_STATIC_CHECK: Exceptions from this category must be handled within
procedures or declared as part of the interface. This is checked by both the
compiler and the runtime environment.
• CX_DYNAMIC_CHECK: Here too, exceptions from this category must be
handled within procedures or declared as part of the interface. This is, however,
not checked statically by the syntax check, but is checked dynamically at the
moment in which an exception of this type is propagated from the procedure.
• CX_NO_CHECK: Neither compiler nor the runtime environment checks whether
an exception that leaves the context of a procedure has also been declared in the
interface.

Catching or Handling of Exceptions

If the exception occurs, the program flow is interrupted, an exception object is generated
and a handler is searched for this exception. As a rule, procedures call other procedures,
creating a corresponding call hierarchy. If an exception is not handled in a procedure, the
system attempts to propagate it to the caller of the procedure. If no handler is found in the
entire call hierarchy, the program terminates with a runtime error and a short dump is
generated. But how exceptions actually caught and what is a handler.

A handler is part of the TRY-ENDTRY control structure for catching exceptions. The
syntax is as follows:

TRY.
[try_block]
[CATCH cx_class1 cx_class2 ... [INTO obj_ref].
[catch_block]
............
[CATCH cx_class3 cx_class4 ... [INTO obj_ref].
[catch_block]
............

307
[CLEANUP [INTO obj_ref].
[cleanup_block]
ENDTRY.

The coding in the TRY block (try_block) defines a protected area whose exceptions
can be handled in the subsequent CATCH blocks. If no exception occurs in the TRY block
and its end reached, processing continues after ENDTRY. If exception occurs in the TRY
block, the system looks for an exception handler in the same or in an outer TRY-
ENDTRY control structures.

The actual exception handlers consist of one or more optional CATCH blocks
(catch_block). These contain the program logic that is executed if the related
exception occurs in the TRY block of the same TRY-ENDTRY control structure. A
CATCH block handles the exceptions from exception classes cx_class1 cx_class2
... along with the exceptions from their respective subclasses. If the INTO addition is
specified, a reference to the exception object is stored in obj_ref, where obj_ref
must be an object reference variable whose static type must be compatible with specified
exception object. When the end of a CATCH block is reached, processing continues after
ENDTRY. The more specific exception classes must always be listed before more general
exception classes.

Consider the example below for catching and handling exceptions.

REPORT z_excep_handling.

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main IMPORTING
ioperand TYPE i.
ENDCLASS. "lcl_example DEFINITION

CLASS lcl_example IMPLEMENTATION.


METHOD main.
DATA: var TYPE i,
error TYPE REF TO cx_root,
txt TYPE string.
TRY.
var = 1 / ioperand.
var = SQRT( ioperand ).
var = ioperand ** ioperand.
CATCH cx_sy_zerodivide INTO error.
txt = error->get_longtext( ).
MESSAGE txt TYPE 'I' DISPLAY LIKE 'E'.
CATCH cx_sy_arg_out_of_domain INTO error.
txt = error->get_longtext( ).
MESSAGE txt TYPE 'I' DISPLAY LIKE 'E'.
CATCH cx_root INTO error.
txt = error->get_longtext( ).
MESSAGE txt TYPE 'I' DISPLAY LIKE 'E'.
ENDTRY.

308
ENDMETHOD. "main
ENDCLASS. "lcl_example IMPLEMENTATION

START-OF-SELECTION.
lcl_example=>main( ioperand = 0 ).
lcl_example=>main( ioperand = -1 ).
lcl_example=>main( ioperand = 100000 ).

In each of the handlers, the relevant error message is output, supplying information about
the precise reason for the error. Following is the output of above code listing.

The general procedure for finding the correct handler for an exception is shown in the
figure below:

309
If an exception occurs and is caught and handled by a handler, the normal control flow of
the program is changed, and a procedure is generally left early. This means that a
program or certain objects may come into an inconsistent status, or that resources have
not been released yet.

The CLEANUP block in TRY-ENDTRY control structure is used to re-establish a


consistent status. The statements in this block are executed if an exception occurs in a
TRY block that is not caught by handler in the same TRY-ENDTRY control structure, but
in a surrounding TRY-ENDTRY control structure. If the INTO addition is specified, a
reference to the exception object is stored in obj_ref, where obj_ref must be an
object reference variable of the CX_ROOT type. After the CLEANUP block has been
executed, the CLEANUP blocks for the surrounding TRY control structures are executed
until the corresponding handler code has been executed. It must be noted that statements
like RETURN or LEAVE TO, which would cause the CLEANUP block to be left early,
result in runtime error. Also, exceptions that occur within CLEANUP block must also be
caught and handled there.

Figure below shows an example of the control flow process when the CLEANUP block is
executed.

310
Raising Exceptions

Exceptions can be raised in two ways: System-driven (by runtime environment) or


Program-driven (by the ABAP program).

The arithmetic statement var = 1/0, for example, causes an exception of the
CX_SY_ZERODIVDE class to be raised by the runtime environment. If the exception is
not caught a runtime error occurs.

Exceptions can be raised in a program-driven manner using the RAISE EXCEPTION


statement.

RAISE EXCEPTION {{TYPE cx_class [EXPORTING p1 = a1 p2 = a2


...]}|obj_ref}.

If the addition TYPE is specified, an exception of the exception class cx_class is


raised and - if necessary - an exception object is created. After TYPE, every exception
class cx_class visible at this point can be specified. With the addition EXPORTING,
you can assign appropriate actual parameters to the input parameters of the instance
constructor using the same syntax as with CREATE OBJECT. For reasons of efficiency,
an exception object is only actually generated if the INTO addition of the CATCH
statement is used for exception handling.

If obj_ref is specified, the exception object must already exist and the obj_ref
reference variable must point to it. This may be the case if the exception has already been
caught once but if the handler wants to raise it again (because it cannot be handled

311
completely, for example) or if the exception object was generated previously by means of
CREATE OBJECT.

In the following example, the predefined exception


cx_sy_dynamic_osql_semantics is raised, for which an exception text and its
placeholder &TOKEN& is filled by passing a value.

REPORT z_raise_exceptions.

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
PRIVATE SECTION.
CLASS-DATA: exp_ref TYPE REF TO cx_sy_dynamic_osql_semantics,
txt TYPE string.
ENDCLASS. "lcl_example DEFINITION

CLASS lcl_example IMPLEMENTATION.


METHOD main.
TRY.
"cx_sy_dynamic_osql_semantics represent the OpenSQL exceptions
"textid, Key for Access to Message Tex
"unknown_table_name, stor value for Attribute textid
RAISE EXCEPTION TYPE cx_sy_dynamic_osql_semantics
EXPORTING
textid = cx_sy_dynamic_osql_semanti
cs=>unknown_table_name
token = 'tbl_student'.

CATCH cx_sy_dynamic_osql_semantics INTO exp_ref.


txt = exp_ref->get_text( ).
MESSAGE txt TYPE 'I' DISPLAY LIKE 'E'.
ENDTRY.
ENDMETHOD. "main
ENDCLASS. "lcl_example IMPLEMENTATION
START-OF-SELECTION.
lcl_example=>main( ).

Following is the output of above code listing.

312
Declaring Exceptions in Procedure Interfaces

As we know that system attempts to propagate an exception, which is not handled in a


procedure, to the caller of the procedure. In the parameter interface of a procedure, the
exceptions that can be propagated from the procedure must be declared. This tells the
caller which exceptions can be expected from the procedure.

To declare an exception in the interface of a procedure, the RASING addition is used, as


the following simplified syntax for method declaration shows:

METHODS meth_name ... RAISING exp1 exp2 ...

In the Class Builder or Function Builder, the declaration is made by listing the exception
classes in the Exceptions tab. The Exception Class checkbox must be selected.

If an exception class is declared in an interface, this declaration also applies to all of its
subclasses. If an exception is not declared, it can not leave a procedure. This raises an
exception from the predefined class CX_SY_NO_HANDLER.

The example in listing below shows the effects of an exception declaration in an


interface.

REPORT z_excep_proc_decl.
CLASS lcl_example DEFINITION.
PUBLIC SECTION.
CLASS-METHODS main.
PRIVATE SECTION.
CLASS-METHODS calculate IMPORTING
ioperand TYPE i
RAISING
cx_sy_zerodivide.
ENDCLASS. "lcl_example DEFINITION

CLASS lcl_example IMPLEMENTATION.

313
METHOD calculate.
DATA var TYPE i.
var = 1 / ioperand.
var = SQRT( ioperand ).
ENDMETHOD. "calculate
METHOD main.
DATA: err_ref TYPE REF TO cx_root,
txt TYPE string.
TRY.
calculate( ioperand = 0 ).
CATCH cx_sy_zerodivide INTO err_ref.
txt = err_ref->get_longtext( ).
CONCATENATE 'CX_SY_ZERODIVDE: ' txt INTO txt
RESPECTING BLANKS.
MESSAGE txt TYPE 'I' DISPLAY LIKE 'E'.
ENDTRY.

TRY.
calculate( ioperand = -1 ).
CATCH cx_sy_arg_out_of_domain INTO err_ref.
txt = err_ref->get_longtext( ).
CONCATENATE 'CX_SY_ARG_OUT_OF_DOMAIN: ' txt INTO txt
RESPECTING BLANKS.
MESSAGE txt TYPE 'I' DISPLAY LIKE 'E'.
CATCH cx_sy_no_handler INTO err_ref.
txt = err_ref->get_longtext( ).
CONCATENATE 'CX_SY_NO_HANDLER: ' txt INTO txt
RESPECTING BLANKS.
MESSAGE txt TYPE 'I' DISPLAY LIKE 'E'.
ENDTRY.
ENDMETHOD. "main
ENDCLASS. "lcl_example IMPLEMENTATION

START-OF-SELECTION.
lcl_example=>main( ).

Within main method, the calculate method is called twice with different parameters.
In the first case, the cx_sy_zerodivide exception is raised by transferring 0. This
exception is declared in the interface of the calculate method. Because the exception
is not handled locally in the calculate method, it is propagated to the caller, in other
words to the main method.

The second time calculate method is called, the value -1 is transferred. This
generates the cx_sy_arg_out_of_domain exception when attempting to determine
the square root. This exception is not declared in the interface; it is therefore not
propagated and cannot be identified by the exception handler in the main method.

The cx_sy_no_handler exception handler prevents the interface violation from


causing a runtime error, but which indicates that the procedure was not implemented
cleanly.

Following is the output of above code listing.

314
The example shows the effects of the violation of the procedure interface in which the
exception was declared. The abstract super classes for all exception class
CX_STATIC_CHECK, CX_DYNAMIC_CHECK and CX_NO_CHECK come into play here
because the response to the interface violation does not have to be the same for all
exception classes. These three categories (static, dynamic and no) determine whether an
explicit declaration must be made and how this is checked. Table below shows in which
cases which exception classes are to be used as a basis.

Creating Exception Classes

All exception classes (global or local) are sub classes of one of the abstract exception
classes described in previous section: CX_STATIC_CHECK, CX_DYNAMIC_CHECK or
CX_NO_CHECK. No specific class can be directly derived from CX_ROOT. The
predefined exception classes (CX_SY_...) inherit from CX_DYNAMIC_CHECK or

315
CX_NO_CHECK but not from CX_STATIC_CHECK. All exception classes must begin
with the prefix CX_, YCX_ or ZCX_. Global exception classes are defined and
managed in the Class Builder (SE24). If the correct naming convention (prefix CX_) and
the class type Exception Class is chosen when a new class is created, the Class Builder
automatically becomes the Exception Builder. Exception classes have the following
features:

Constructor

The constructor must have a predefined structure and a specific interface. With global
classes, the Class Builder generates the correct constructor and sets it to an unchangeable
status. The constructor has two IMPORTING parameters:

• TEXTID: This parameter can be used to determine which of your exception texts
the exception will use.
• PREVIOUS: This parameter can be used to assign the PREVIOUS attribute of an
exception class a previous exception.

Methods

In exception classes, we can define our own methods. The following two predefined
methods are inherited from the root class CX_ROOT:

• GET_TEXT and GET_LONGTEXT: These methods return the exception text or


the long text of the exception text (controlled by the TEXTID attribute) as a
character string of the string type.
• GET_SOURCE_POSITION: Returns the program name, the name of a possible
include program, and the line number of the statement that raised the exception.

Attributes

The following attributes are inherited from CX_ROOT:

• TEXTID: Used to specify the exception of a class more precisely by using


several exception texts. The attribuet is genrally set by the constructor, and
influences the result of the GET_TEXT method.
• PREVIOUS: Can contain a reference to a previous exception. The attribute is
particularly useful, because it enables exceptions to be chained. This means that
we can track the path of an exception right back to its origin.

316
Each exception is assigned an explanatory text. The exception text describes an error
situation from a technical view. Exception texts can contain parameters (placeholders)
that enable an error situation to be described more precisely. We can convert attributes
into parameters of exception texts by displaying their name using the character '&' in the
exception text. If the exception occurs, the parameters are replaced by the content of the
attributes. There are two ways of defining exception texts:

• Exception Texts in Online Text Repository: The Online Text Repository (OTR)
is a central repository for text and provides services for the processing and
administration. The text stored in the OTR can contain a maximum of 255
characters.
• Exception Texts in Table T100: If the exception class implements the interface
if_t100_message, the short texts for messages in the database table T100 are
used as exception texts. The text is identified by the message class and the
message number. Note that here the message class is not a class in the sense of
object orientation rather it is an identifier that groups messages in an application
area. Attributes from the exception class can be assigned to placeholders &1 to
&4 or & in the message. These texts can contain a maximum of 72 characters and
can be sent to the program user during exception handling with the MESSAGE
obj_ref statement.

In the first example we define our own exception class, to which we assigned two
alternative OTR texts.

317
Next we created another exception ID with name ZCX_EXCEPTION_EXAMPLE02. In
addition, we have assigned a relevant text to the two exception IDs congaing a place
holder &TOKEN& to parameterize the output.

For each exception text, the Class Builder creates a static constant with the same name as
the exception text. This can be passed to the TEXTID parameter of the constructor to
determine the exception text when the exception is raised. If the parameter is not passed,
a predefined exception text is used. Another attribute TOKEN (with same name as the
parameter) of type string must be created.

318
The following code consumes the zcx_exception_example.

REPORT z_excep_decl01.

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS. "lcl_example DEFINITION

CLASS lcl_example IMPLEMENTATION.


METHOD main.
DATA: err_ref TYPE REF TO zcx_exception_example,
txt TYPE string.
TRY.
RAISE EXCEPTION TYPE zcx_exception_example EXPORTING
textid = zcx_exception_example=>zcx
_exception_example
token = '"100"'.
CATCH zcx_exception_example INTO err_ref.
txt = err_ref->get_text( ).
MESSAGE txt TYPE 'I' DISPLAY LIKE 'E'.
ENDTRY.
TRY.
RAISE EXCEPTION TYPE zcx_exception_example EXPORTING
textid = zcx_exception_example=>zcx
_exception_example02
token = '"200"'.
CATCH zcx_exception_example INTO err_ref.
txt = err_ref->get_text( ).
MESSAGE txt TYPE 'I' DISPLAY LIKE 'E'.
ENDTRY.
ENDMETHOD. "main
ENDCLASS. "lcl_example IMPLEMENTATION

START-OF-SELECTION.
lcl_example=>main( ).

After execution the following output is produced.

319
The next example demonstrates the usage of exception texts from database table T100.

First to create the message class, open the message transaction tool (SE91) and create the
zexcp_msg_cls as shown below:

Create a new class ZCX_EXCEPTION_EXAMPLE_T100 and select the With Message


Class checkbox. In this case the if_t100_message is included in the class definition
automatically and prepare the Class Builder to use messages as exception texts.

320
In the Attributes tab, the two attributes TOKEN1 and TOKEN2 are defined as
placeholders.

Next to define message texts, go to Texts tab. Place the cursor in the line with the
corresponding exception ID, and click on the Message Text button the system displays an
input template where we entered the message class already created.

321
The following example utilizes the above exception class.

REPORT z_excep_decl02.

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS. "lcl_example DEFINITION

CLASS lcl_example IMPLEMENTATION.


METHOD main.
DATA err_ref TYPE REF TO zcx_exception_example_t100.
TRY.
RAISE EXCEPTION TYPE zcx_exception_example_t100 EXPORTING
token1 = '"5
00"'
token2 = '"F
ive Hunderd"'.
CATCH zcx_exception_example_t100 INTO err_ref.
MESSAGE err_ref TYPE 'I' DISPLAY LIKE 'E'.
ENDTRY.
ENDMETHOD. "main
ENDCLASS. "lcl_example IMPLEMENTATION

START-OF-SELECTION.
lcl_example=>main( ).

Following is the output of above code listing.

322
Classic Exception Handling
For reasons of downward compatibility, these older concepts can still be used to handle
exceptions in ABAP. However, these concepts should no longer be used in new
programs. The classic exceptions handling has the following types:

Catchable Runtime Errors

If runtime errors are caused by situations that can be handled in a meaningful way in the
program, they are catchable. Catchable runtime errors are grouped into exception groups
that allow similar errors to be handled together. We can handle catchable runtime errors
with the following statement:

CATCH SYSTEM-EXCEPTIONS exc1 = rc1 … excn = rcn.


………………….
ENDCATCH.

The exc expressions describe either a catchable runtime error or the name of an
exception group. The rc expressions are numeric literals. If one of the specified runtime
errors occurs in the statement block between CATCH and ENDCATCH the program does
not terminate. Instead, after ENDCATCH, the numeric value rc assigned to the runtime
error, which is available as a return value in the sy-subrc system field.

The CATCH and ENDCATCH statements define control structures that can be nested as
deeply as we require. It must be noted that CATCH SYSTEM-EXCEPTIONS can only be
used to catch runtime errors form the current call level and not from called procedures.

The following example demonstrates how to use the catchable runtime errors.

REPORT z_classic_catchable_errors.

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS. "lcl_example DEFINITION

323
CLASS lcl_example IMPLEMENTATION.
METHOD main.
DATA var TYPE i.
CATCH SYSTEM-EXCEPTIONS arithmetic_errors = 4.
var = 1 / 0.
ENDCATCH.
IF sy-subrc = 4.
MESSAGE 'Division by Zero error' TYPE 'I'
DISPLAY LIKE 'E'.
ENDIF.
ENDMETHOD. "main
ENDCLASS. "lcl_example IMPLEMENTATION

START-OF-SELECTION.
lcl_example=>main( ).

The division by 0 causes the catchable runtime error COMPUTE_INT_ZERODIVIDE,


which is contained in the exception group ARITHMETIC_ERRORS. In this case, sy-
subrc is set to 4. Following is the output of above code listing.

Self-Defined (Non-Class-Based) Exceptions

Self-defined (non-class-based) exceptions can be defined in the interfaces of function


modules and methods. For local class methods, the definition is carried out by assigning a
name for the exception after the EXCEPTIONS addition of the [CLASS-]METHODS
statement. For methods of global classes or function modules, the definition is carried out
by assigning a name of the exception in the Class Builder or Function Builder in the
Exceptions tab where the Exception Classes checkbox is not selected here.

The following statement is used to raise the self-defined (non-class-based) exceptions.

RAISE exc.

Raising exception terminates the procedure and the sy-subrc system field is set. The
RAISE EXCEPTION statement for raising class-based exceptions must not be used in

324
the same procedure and no class-based exceptions can be declared in the interface with
RAISING.

Self-defined (non-class-based) exceptions are rendered treatable using the


EXCREPTIONS addition of the CALL METHOD and CALL FUNCTION statements.
This is achieved by assigning numeric values to exceptions, which are moved to the sy-
subrc system field when the exception occurs; however, the actual handling is carried
out after the call by evaluating sy-subrc. If an exception that is raised in the procedure
has not been assigned a numeric value, a runtime error occurs.

Listing below demonstrate the self-defined (non-class-based) exceptions.

REPORT z_non_cls_based_excp.

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS: main,
divide IMPORTING
inumerator TYPE i
idenominator TYPE i
EXPORTING
eresult TYPE i
EXCEPTIONS
divide_zero.
ENDCLASS. "lcl_example DEFINITION

CLASS lcl_example IMPLEMENTATION.


METHOD divide.
IF idenominator = 0.
"Type A represents the termination messages
"The message text is placed in the system field MSGV1
"RAISING addition,the statement MESSAGE raises a
"non-class-based exception
MESSAGE 'Division by 0' TYPE 'A'
RAISING divide_zero.
ELSE.
eresult = inumerator / idenominator.
ENDIF.
ENDMETHOD. "divide
METHOD main.
DATA result TYPE i.
divide( EXPORTING
inumerator = 1
idenominator = 0
IMPORTING
eresult = result
EXCEPTIONS
divide_zero = 4 ).
IF sy-subrc = 4.
MESSAGE sy-msgv1 TYPE 'I' DISPLAY LIKE 'E'.
ENDIF.
divide( EXPORTING
inumerator = 1

325
idenominator = 0
IMPORTING
eresult = result ).
ENDMETHOD. "divide
ENDCLASS. "lcl_example IMPLEMENTATION

START-OF-SELECTION.
lcl_example=>main( ).

We call the divide method twice with the denominator 0 so that the exception is raised
each time. The exception is handled during the first call. In this case, the system behaves
as it does when the RAISE statement is used. We can replace the RAISE statement with
MESSAGE … RAISING. The second time the method is called, the exception is not
handled. In this case, the message is processed according to the specified message type
(“A”), and the program terminates. Following screen shot shows the output of the above
code listing.

Combining Class-Based and Classic Exceptions


As we know from previous sections, classic exceptions that can be defined by the
EXCEPTIONS clause in methods and function modules are completely different concepts
from those that can be defined by the RAISING clause in class-based exceptions. The
two concepts can not be mixed. Therefore, we must distinguish strictly between the two
concepts.

As developers, we must opt for class-based exceptions, but you may call procedure which
still uses the classic exception concepts. For example, when we call a function module
that uses classic exceptions within a method where we are using class-based exceptions.

In this case, the classic exceptions must be caught, and a new, corresponding class-based
exception must be raised as shown in the following example.

326
REPORT z_classic_cls_based_exp.

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS: main,
divide IMPORTING
inumerator TYPE i
idenominator TYPE i
EXPORTING
eresult TYPE i
EXCEPTIONS
divide_zero,
perform_cal RAISING
cx_sy_zerodivide.
ENDCLASS. "lcl_example DEFINITION

CLASS lcl_example IMPLEMENTATION.


METHOD divide.
IF idenominator = 0.
RAISE divide_zero.
ELSE.
eresult = inumerator / idenominator.
ENDIF.
ENDMETHOD. "divide
METHOD perform_cal.
DATA result TYPE i.
divide( EXPORTING
inumerator = 1
idenominator = 0
IMPORTING
eresult = result
EXCEPTIONS
divide_zero = 4 ).
IF sy-subrc = 4.
RAISE EXCEPTION TYPE cx_sy_zerodivide.
ELSE.
WRITE: / result .
ENDIF.
ENDMETHOD. "divide
METHOD main.
DATA err_ref TYPE REF TO cx_sy_zerodivide.
TRY.
perform_cal( ).
CATCH cx_sy_zerodivide INTO err_ref.
MESSAGE err_ref TYPE 'I' DISPLAY LIKE 'E'.
ENDTRY.
ENDMETHOD. "divide
ENDCLASS. "lcl_example IMPLEMENTATION

START-OF-SELECTION.
lcl_example=>main( ).

Following output is produced after the execution of above report.

327
Assertions
An assertion is the confirmation that a specific status of the data objects in a program
actually exists. Assertions are typically used to ensure or check a consistent status at
specific points in the program flow. Therefore, assertion generally expresses an
assumption that must apply in order for the program to continue to be executed.

Using assertions can help to find more errors in the program and to improve the quality of
a program. Assertions can be activated or deactivated so that checks do not affect the
speed of any productive programs. The syntax for the ASSERT statement is:

ASSERT [{ID group} CONDITION] log_exp.

An assertion that is always active is expressed by just the logical expression log_exp
after the ASSERT statement. If the result of the check is true, the program flow continues
as normal. If the result is false, the program terminates with the non-catchable runtime
error ASSERTION_FAILED.

If the ID group addition is specified, an assertion is defined that can be activated


externally by linking it to a so called checkpoint group. The check point group is an
ABAP repository object. The behavior of the assertion can be managed externally by
changing the checkpoint group with Checkpoints that Can Be Activated (TCode SAAB).
The following settings are possible:

• Inactive: In this case, the statement does not have any impact on the program
flow.
• Log: if an incorrect result is delivered, an entry is written in a special log, which
can also be evaluated in Checkpoints that Can Be Activated (TCode SAAB). The
program execution then continues with the statement following ASSERT.
• Abort: This option generates the same behavior as an assertion that is always
active. An untreatable exception is raised, and the program terminates with the
ASSERTION_FAILED runtime error.
• Break/Log or Break/Abort: If an incorrect result is delivered, the program
branches to the ABAP Debugger.

328
Exceptions focus more on the “robustness” of the program i.e. a program should still be
able to run, even if it is faced with meaningless user entries. Assertions on the other hand,
focus on “correctness” of the program i.e. the focus is on implementing a program so that
it corresponds exactly to its specification.

The assertions can be used to implement the software development principle, “design by
contract (DbC)”. For that reason ASSERT is used at the start of method to check the
pre-condition according to which the method may actually be executed. At the end of the
method, a post-condition is checked, which states whether the method has functioned
correctly.

The example on next page demonstrates assertions.

329
To create a checkpoint group, open Checkpoints that Can Be Activated (TCode SAAB).
On initial screen enter the name for checkpoint group in Checkpoint Group frame and
click on the Create button.

330
On activation tab leave default values and click Save.

331
By default activatable checkpoints are always inactive. To activate the assertion, on the
initial screen of Checkpoints that Can Be Activated (TCode SAAB), click on the Active
button. On the resulting Activation tab select the Abort from Assertions (Forground) sub
frame, and click Save, as shown below.

Now this assertion is exclusively activated for you (by using personal activation setting).

The following code listing uses the above assertion as:

REPORT z_assertion.

CLASS lcl_example DEFINITION.


PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS. "lcl_example DEFINITION

CLASS lcl_example IMPLEMENTATION.


METHOD main.
DATA var TYPE i.
ASSERT ID zchk_point_grp
CONDITION var IS NOT INITIAL.
ENDMETHOD. "main
ENDCLASS. "lcl_example IMPLEMENTATION

START-OF-SELECTION.
lcl_example=>main( ).

332
After execution the program will terminate with runtime error ASSERTION_FAILED
and a short dump will show the position where the assertion was failed.

333
334

Вам также может понравиться