+ All Categories
Home > Documents > code writing.pdf

code writing.pdf

Date post: 28-Oct-2015
Category:
Upload: susmita099
View: 59 times
Download: 3 times
Share this document with a friend
Description:
code writing
Popular Tags:
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 (4 th 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
Transcript
Page 1: code writing.pdf

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

Page 2: code writing.pdf

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

Page 3: code writing.pdf

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

Page 4: code writing.pdf

• 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

Page 5: code writing.pdf

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

Page 6: code writing.pdf

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

Page 7: code writing.pdf

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

Page 8: code writing.pdf

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

Page 9: code writing.pdf

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

Page 10: code writing.pdf

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

Page 11: code writing.pdf

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

Page 12: code writing.pdf

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

Page 13: code writing.pdf

• 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

Page 14: code writing.pdf

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

Page 15: code writing.pdf

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

Page 16: code writing.pdf

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

Page 17: code writing.pdf

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

Page 18: code writing.pdf

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

Page 19: code writing.pdf

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

Page 20: code writing.pdf

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

Page 21: code writing.pdf

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

Page 22: code writing.pdf

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_MyPackageb) Description: My Training and Demo Programsc) 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

Page 23: code writing.pdf

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

Page 24: code writing.pdf

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

Page 25: code writing.pdf

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

Page 26: code writing.pdf

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

Page 27: code writing.pdf

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

Page 28: code writing.pdf

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

Page 29: code writing.pdf

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

Page 30: code writing.pdf

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

Page 31: code writing.pdf

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

Page 32: code writing.pdf

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

Page 33: code writing.pdf

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_HWClass Type: Usual ABAP ClassBrief Description: My hello world classInstantiation: Public Final: Check (Means that this class can’t be inherited)

33

Page 34: code writing.pdf

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: msgLevel: Instance AttributeVisibility: PrivateTyping: TypeAssociated Type: string

34

Page 35: code writing.pdf

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: InstanceVisibility: PublicDescription: 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

Page 36: code writing.pdf

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

Page 37: code writing.pdf

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

Page 38: code writing.pdf

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_HWShort Text: Hello World Start Object: Method of a class and Select Continue.

38

Page 39: code writing.pdf

20. On next screen maintain OO transaction.OO Transaction Model: Uncheck (to fill the input fields)Class Name: z_cl_clientMethod: mainLocal in Program: CheckLocal in Program: Z_OO_HW

21. Click Save on standard toolbar.

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

39

Page 40: code writing.pdf

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

Page 41: code writing.pdf

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

Page 42: code writing.pdf

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

Page 43: code writing.pdf

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

Page 44: code writing.pdf

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

Page 45: code writing.pdf

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

Page 46: code writing.pdf

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

Page 47: code writing.pdf

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

Page 48: code writing.pdf

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

Page 49: code writing.pdf

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

Page 50: code writing.pdf

‘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

Page 51: code writing.pdf

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

Page 52: code writing.pdf

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

Page 53: code writing.pdf

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

Page 54: code writing.pdf

Data Type LengthStandard Length

Initial Value Meaning

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

c1 - 65535 characters

1 character ‘….’Text Field (Alpha numeric)

n1 - 65535 characters

1 character '0 … 0'Numeric Text

Field (Numeric characters)

d 8 characters ‘00000000'Date Field (Format: YYYYMMDD)

t 6 characters '000000'Time Field (Format: HHMMSS))

Hexadecimal (Byte) Data Type

x 1-65535 bytes 1 byte x'00 …00'Hexadecimal field

• Variable Length Elementary Data Types

Data Type LengthStandard Length

Initial Value Meaning

Character Data Types

string Character Stringsxstring 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

Page 55: code writing.pdf

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

Page 56: code writing.pdf

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

Page 57: code writing.pdf

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

Page 58: code writing.pdf

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

Page 59: code writing.pdf

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

Page 60: code writing.pdf

• 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

Page 61: code writing.pdf

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

Page 62: code writing.pdf

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

Page 63: code writing.pdf

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

Page 64: code writing.pdf

[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

Page 65: code writing.pdf

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

Page 66: code writing.pdf

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 TABLEOF data_type|data_objectWITH [NON-]UNIQUE KEY col1…coln.

TYPES tab_name TYPE STANDARD|SORTED|HASHED TABLEOF data_typeWITH [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

Page 67: code writing.pdf

After executing the loop will display five message boxes as:

67

Page 68: code writing.pdf

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

Page 69: code writing.pdf

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

Page 70: code writing.pdf

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

Page 71: code writing.pdf

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

clikec, d, n, t, string, and flat structures containing character like components

csequence c and string (text like types)xsequence x and xstring (byte like types)any table All table typessorted table Sorted tableshashed table Hashed tablesindex table Standard and Sorted tablesstandard table, table Standard tablesnumeric i (b,s), p , f (numeric types)

c, n, p, x Corresponding built-in types with generic lengths and decimal places

simplec, d, f, i (b,s), n, p, t, string, x, xstring, and flat 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

Page 72: code writing.pdf

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

Page 73: code writing.pdf

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 Type

DescriptionABAP Type

ACCP

Posting Period: The length is set to 6 places for this data type. The format is YYYYMM. In input and output, a point is inserted between the year and month, so the template of this data type has the form ‘____.__’.

n

CHAR

Character string: Fields of type CHAR may have a maximum length of only 255 in tables. If longer character fields are to be used in tables, you must choose data type LCHR. There are no restrictions on the length of such fields in structures.

c

CLNT Client: Client fields always have three places. c

CUKYCurrency key: Fields of this type are referenced by fields of type CURR. The length is set to 5 places for this data type.

c

73

Page 74: code writing.pdf

CURR

Currency field: Equivalent to an amount field DEC. A field of this type must refer to a field of type CUKY (reference field). The maximum length for this data type is 31 places.

p

DATSDate: The length is set to 8 places for this data type. The output template can be defined with the user profile.

d

DECCounter or amount field: with decimal point, sign, and commas separating thousands. A DEC field has a maximum length of 31 places.

p

FLTPFloating point number: The length (including decimal places) is set to 16 places for this data type.

f

INT11-byte integer: between 0 and 255. The length is set to 3 places for this data type.

b

INT2

2-byte integer: between -32767 and 32767. Fields of this type should only be used for length fields. With INSERT or UPDATE on the long field, the database interface enters the length which was actually used in the length field. The length is set to 5 places for this data type.

s

INT44-byte integer: between -2147483647 bis 2147483647. The length is set to 10 places for this data type.

i

LANGLanguage key: This data type always has length 1. The language key is displayed at the user interface with 2 places, but is only stored with 1 place in the database.

c

LCHAR

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 filled with the length actually required. If the length field 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.

c

LRAW

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 filled with the length actually required. If the length field 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.

x

NUMCNumeric text: Long character field in which only numbers can be entered. The length of this field is limited to a maximum of 255 places.

n

PRECPrecession: Accuracy of a QUAN field. The length is set to 2 places for this data type.

s

QUAN

Quantity. Equivalent to an amount field DEC. A field of this type must always refer to units field with UNIT format (reference field). The maximum length for this data type is 31 places.

p

74

Page 75: code writing.pdf

RAWByte string: Fields of type RAW may have only a maximum length of 255 in tables. If longer raw fields are required in tables, you should select data type LRAW.

x

RAWSTRING

Variable byte string: In the Dictionary a length can be specified for this type (at least 256 characters). As default for the output length 132 characters are proposed. You cannot attach search helps to components of this type.

xstring

STRING

Variable character string: In the Dictionary a length can be specified for this type (at least 256 characters). As default for the output length 132 characters are proposed. You cannot attach search helps to components of this type.

string

SSTRING

Short character string: In the Dictionary the number of characters can be specified for this type (1-255). String fields of this type can be used in indexes and in the WHERE condition of a SELECT statement. You cannot use them in table keys.

string

TIMSTime: The length is set to 6 places for this data type. The format is hhmmss. The template for input and output has the form ‘__.__.__’.

t

UNITUnit: Fields of this type are referenced by fields of type QUAN. The length of this data type is set to 2 or 3 places.

c

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

Page 76: code writing.pdf

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

Page 77: code writing.pdf

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

Page 78: code writing.pdf

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

Page 79: code writing.pdf

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

Page 80: code writing.pdf

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

Page 81: code writing.pdf

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

Page 82: code writing.pdf

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

Page 83: code writing.pdf

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

Page 84: code writing.pdf

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

Page 85: code writing.pdf

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

Page 86: code writing.pdf

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 EditIncludeInsert 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

Page 87: code writing.pdf

1. Place the cursor under the line in which you want to insert the include and choose EditIncludeInsert.

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

Page 88: code writing.pdf

88

Page 89: code writing.pdf

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

Page 90: code writing.pdf

90

Page 91: code writing.pdf

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

Page 92: code writing.pdf

For All Data TypesOption Function

LEFT-JUSTIFIED Output is left-justified.CENTERED Output is centered.RIGHT-JUSTIFIED Output is right-justified.

NO-ZEROIf a field contains only zeros, these are replaced by blanks. For type C and N fields, leading zeros are replaced automatically.

For Numeric FieldsNO-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 FieldsDD/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

Page 93: code writing.pdf

The above code produces the following output.

93

Page 94: code writing.pdf

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

Page 95: code writing.pdf

• 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

Page 96: code writing.pdf

96

Page 97: code writing.pdf

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

Page 98: code writing.pdf

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

Page 99: code writing.pdf

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, dFragment 2: Alignment gap between d and eFragment 3: eFragment 4: f, gFragment 5: Alignment gap between g and hFragment 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

Page 100: code writing.pdf

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

Page 101: code writing.pdf

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

Page 102: code writing.pdf

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 Functionsabs( 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 Functionsacos( x ), asin( x ), atan( x ) , cos( x ), sin( x ), tan( x)

Trigonometric functions.

cosh( x ), sinh( x ), tanh( x ) Hyperbolic functions.

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

Page 103: code writing.pdf

103

Page 104: code writing.pdf

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

Page 105: code writing.pdf

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

AND Combine two logical expression

( c < n ) AND ( n > f )

---

OR Combine two logical expression

( c < n ) OR ( n > f )

---

NOT Negate the result of logical expression

NOT ( c < n ) ---

String Comparison OperatorsCO 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

Page 106: code writing.pdf

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

Page 107: code writing.pdf

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 NPsel_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

Page 108: code writing.pdf

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

Page 109: code writing.pdf

109

Page 110: code writing.pdf

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

Page 111: code writing.pdf

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

Page 112: code writing.pdf

The above code produces the following output.

112

Page 113: code writing.pdf

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_blockENDDO.

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

Page 114: code writing.pdf

114

Page 115: code writing.pdf

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_blockENDWHILE.

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

Page 116: code writing.pdf

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

Page 117: code writing.pdf

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

Page 118: code writing.pdf

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

Page 119: code writing.pdf

119

Page 120: code writing.pdf

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

Page 121: code writing.pdf

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

Page 122: code writing.pdf

122

Page 123: code writing.pdf

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

123

Page 124: code writing.pdf

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

Page 125: code writing.pdf

The above code produces the following code.

125

Page 126: code writing.pdf

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

Page 127: code writing.pdf

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

Page 128: code writing.pdf

The above code produces the following output.

Component Assignment

To dynamically address the components of structure, use the following variant of ASSIGN statement.

128

Page 129: code writing.pdf

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

Page 130: code writing.pdf

The above code produces the following output.

130

Page 131: code writing.pdf

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

Page 132: code writing.pdf

The above code produces the following output.

132

Page 133: code writing.pdf

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

Page 134: code writing.pdf

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

Page 135: code writing.pdf

The above coding produces the following output.

135

Page 136: code writing.pdf

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

Page 137: code writing.pdf

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 TABLEOF data_type|data_object WITH [NON-]UNIQUE KEY col1…coln [INITIAL SIZE n].

TYPES tab_name TYPE STANDARD|SORTED|HASHED TABLEOF 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

Page 138: code writing.pdf

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

Page 139: code writing.pdf

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

Page 140: code writing.pdf

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

Page 141: code writing.pdf

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

Page 142: code writing.pdf

"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

Page 143: code writing.pdf

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

Page 144: code writing.pdf

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

Page 145: code writing.pdf

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

Page 146: code writing.pdf

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

Page 147: code writing.pdf

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

Page 148: code writing.pdf

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

Page 149: code writing.pdf

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

Page 150: code writing.pdf

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

Page 151: code writing.pdf

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

Page 152: code writing.pdf

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

Page 153: code writing.pdf

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

Page 154: code writing.pdf

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

Page 155: code writing.pdf

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

Page 156: code writing.pdf

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

Page 157: code writing.pdf

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

Page 158: code writing.pdf

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

Page 159: code writing.pdf

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

Page 160: code writing.pdf

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

Page 161: code writing.pdf

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 PARAMETERSPARAMETERS 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

Page 162: code writing.pdf

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

Page 163: code writing.pdf

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

Page 164: code writing.pdf

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

Page 165: code writing.pdf

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

Page 166: code writing.pdf

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

Page 167: code writing.pdf

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

Page 168: code writing.pdf

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

Page 169: code writing.pdf

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

Page 170: code writing.pdf

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

Page 171: code writing.pdf

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

Page 172: code writing.pdf

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

Page 173: code writing.pdf

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

Page 174: code writing.pdf

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

Page 175: code writing.pdf

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

Page 176: code writing.pdf

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

Page 177: code writing.pdf

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

Page 178: code writing.pdf

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

Page 179: code writing.pdf

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

Page 180: code writing.pdf

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

Page 181: code writing.pdf

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

Page 182: code writing.pdf

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

Page 183: code writing.pdf

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

Page 184: code writing.pdf

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

Page 185: code writing.pdf

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

Page 186: code writing.pdf

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

Page 187: code writing.pdf

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

Page 188: code writing.pdf

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

Page 189: code writing.pdf

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

Page 190: code writing.pdf

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

Page 191: code writing.pdf

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

Page 192: code writing.pdf

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

Page 193: code writing.pdf

• 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

Page 194: code writing.pdf

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

Page 195: code writing.pdf

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

Page 196: code writing.pdf

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

Page 197: code writing.pdf

"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

Page 198: code writing.pdf

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

Page 199: code writing.pdf

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

Page 200: code writing.pdf

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

Page 201: code writing.pdf

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

Page 202: code writing.pdf

… 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

Page 203: code writing.pdf

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

Page 204: code writing.pdf

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 EXPORTINGparam 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

Page 205: code writing.pdf

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

Page 206: code writing.pdf

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 CHANGINGcpare type data_type OPTIONAL …

Or

METHODS my_meth CHANGINGcpare 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

Page 207: code writing.pdf

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

Page 208: code writing.pdf

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

Page 209: code writing.pdf

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( EXPORTINGipara1 = dobj1ipara2 = dobj2 …

IMPORTINGopara1 = dobj1opara2 = dobj2 …

CHANGINGcpara1 = dobj1cpara2 = 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( EXPORTINGipara1 = dobj1ipara2 = dobj2 ….

RECEIVINGrpara = 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

Page 210: code writing.pdf

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

Page 211: code writing.pdf

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

Page 212: code writing.pdf

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 filesPARAMETERS: 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

Page 213: code writing.pdf

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

Page 214: code writing.pdf

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 DEFINITIONCREATE 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

Page 215: code writing.pdf

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

Page 216: code writing.pdf

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

Page 217: code writing.pdf

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

Page 218: code writing.pdf

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

Page 219: code writing.pdf

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 DEFINITIONCREATE PRIVAE FRIENDS c1.

.........ENDCLASS.

219

Page 220: code writing.pdf

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

Page 221: code writing.pdf

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

Page 222: code writing.pdf

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 DEFINITIONCREATE PUBLIC|PROTECTED|PRIVATE.

PUBLIC SECTIONS.METHODS constructor

[IMPORTING I TYPE tye … ]…………………

ENDCLASS.

CLASS lcl_myclass IMPLEMENTATION.METHOD constructor.

…………

222

Page 223: code writing.pdf

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

Page 224: code writing.pdf

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

Page 225: code writing.pdf

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

Page 226: code writing.pdf

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

Page 227: code writing.pdf

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

Page 228: code writing.pdf

To create a local type in a class pool, select GotoClass-local TypeLocal 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 GotoClass-local TypeLocal Class definitions/Types or Local Types and to implement the local classes, select GotoClass-local TypesLocal 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

Page 229: code writing.pdf

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

Page 230: code writing.pdf

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

Page 231: code writing.pdf

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

Page 232: code writing.pdf

12. Following output is produced after executing the above code.

232

Page 233: code writing.pdf

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 DEFINITIONINHERITING 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

Page 234: code writing.pdf

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_speedENDCLASS. "lcl_vehicle IMPLEMENTATION

234

Page 235: code writing.pdf

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. "unloadENDCLASS. "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

Page 236: code writing.pdf

truck_ref->show_speed( ). SKIP. truck_ref->unload( ). ENDMETHOD. "mainENDCLASS. "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

Page 237: code writing.pdf

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

Page 238: code writing.pdf

In the Class Builder, we redefine an inherited method by displaying it on the Methods tab. To do so, we must use the UtilitiesSettings 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_speedENDCLASS. "lcl_vehicle IMPLEMENTATION

CLASS lcl_car DEFINITION INHERITING FROM lcl_vehicle. PUBLIC SECTION.

238

Page 239: code writing.pdf

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_speedENDCLASS. "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

Page 240: code writing.pdf

me->freight = ifreight. ENDMETHOD. "load

METHOD unload. CLEAR me->freight. WRITE: 'Truck is uloaded', me->freight. ENDMETHOD. "unloadENDCLASS. "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. "mainENDCLASS. "lcl_example IMPLEMENTATION

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

Following is the out put of above listing.

240

Page 241: code writing.pdf

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

Page 242: code writing.pdf

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. "accelerateENDCLASS. "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_speedENDCLASS. "lcl_car IMPLEMENTATION

CLASS lcl_truck DEFINITION INHERITING FROM lcl_vehicle. PUBLIC SECTION.

242

Page 243: code writing.pdf

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. "unloadENDCLASS. "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

Page 244: code writing.pdf

truck_ref->accelerate( 110 ). truck_ref->show_speed( ). SKIP. truck_ref->unload( ). ENDMETHOD. "mainENDCLASS. "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

Page 245: code writing.pdf

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

Page 246: code writing.pdf

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. "mainENDCLASS. "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

Page 247: code writing.pdf

• 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 implementedsuper->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

Page 248: code writing.pdf

DATA name TYPE string.ENDCLASS. "lcl_vessel DEFINITION

CLASS lcl_vessel IMPLEMENTATION. METHOD constructor. name = iname. WRITE: / 'lcl_vessel:constructor, name=', name. ENDMETHOD. "constructorENDCLASS. "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. "constructorENDCLASS. "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

Page 249: code writing.pdf

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. "mainENDCLASS. "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

Page 250: code writing.pdf

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. "constructorENDCLASS. "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. "constructorENDCLASS. "lcl_motorship IMPLEMENTATION

CLASS lcl_example DEFINITION. PUBLIC SECTION. CLASS-METHODS main.ENDCLASS. "lcl_example DEFINITION

250

Page 251: code writing.pdf

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. "mainENDCLASS. "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

Page 252: code writing.pdf

• 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

Page 253: code writing.pdf

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

Page 254: code writing.pdf

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 GotoInterface Section.

254

Page 255: code writing.pdf

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

Page 256: code writing.pdf

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

Page 257: code writing.pdf

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_speedENDCLASS. "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_speedENDCLASS. "lcl_electron IMPLEMENTATION

CLASS lcl_example DEFINITION. PUBLIC SECTION. CLASS-METHODS main. PRIVATE SECTION.

257

Page 258: code writing.pdf

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_exampleENDCLASS. "lcl_example IMPLEMENTATION

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

The output of the above code listing is shown below:

258

Page 259: code writing.pdf

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 interface'.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. "mainENDCLASS. "lcl_example IMPLEMENTATION

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

Following is the output of the above example.

259

Page 260: code writing.pdf

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

Page 261: code writing.pdf

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

Page 262: code writing.pdf

....... 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

Page 263: code writing.pdf

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_speedENDCLASS. "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

Page 264: code writing.pdf

msg = me->speed_over_c. CONCATENATE 'Electron Speed/C: ' msg INTO msg. WRITE / msg. ENDMETHOD. "lif_drive_object~show_speedENDCLASS. "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_exampleENDCLASS. "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

Page 265: code writing.pdf

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

Page 266: code writing.pdf

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

Page 267: code writing.pdf

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

Page 268: code writing.pdf

• 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

Page 269: code writing.pdf

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. "hungryENDCLASS. "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. "fastingENDCLASS. "lcl_lion IMPLEMENTATION

CLASS lcl_example DEFINITION. PUBLIC SECTION. CLASS-METHODS main.ENDCLASS. "lcl_example DEFINITION

CLASS lcl_example IMPLEMENTATION.

269

Page 270: code writing.pdf

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 reference 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 inthe 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. "mainENDCLASS. "lcl_example IMPLEMENTATION

270

Page 271: code writing.pdf

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

Page 272: code writing.pdf

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_speedENDCLASS. "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~accelerateENDCLASS. "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

Page 273: code writing.pdf

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 edited "using the Transformation Editor (STRANS). First parameter 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 control CALL FUNCTION 'DISPLAY_XML_STRING' EXPORTING xml_string = xml_str. ENDMETHOD. "serializeENDCLASS. "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

Page 274: code writing.pdf

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

Page 275: code writing.pdf

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. "speakENDCLASS. "lcl_cat IMPLEMENTATION

CLASS lcl_dog IMPLEMENTATION. METHOD get_type. WRITE: 'Dog'. ENDMETHOD. "get_type

METHOD speak. WRITE: 'Bark'. ENDMETHOD. "speak

275

Page 276: code writing.pdf

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. "playENDCLASS. "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. "mainENDCLASS. "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

Page 277: code writing.pdf

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

Page 278: code writing.pdf

3. Create and activate the global abstract class z_cl_account as shown below:

278

Page 279: code writing.pdf

4. Next to implement the methods of z_cl_account, double click each method to write code for it, as show below:

279

Page 280: code writing.pdf

5. The following concrete global class z_cl_checking_account specializes the abstract z_cl_account as shown below:

280

Page 281: code writing.pdf

6. The redefined withdraw method of concrete global class z_cl_savings_account throws an exception when the account is overdrawn.

281

Page 282: code writing.pdf

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

Page 283: code writing.pdf

METHODS handle_debit_balance FOR EVENT overdraw OF z_cl_checking_account 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 text. MESSAGE text TYPE 'I'. ENDMETHOD. "handle_debit_balanceENDCLASS. "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

Page 284: code writing.pdf

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. "mainENDCLASS. "lcl_example IMPLEMENTATION

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

Following is the output of above example.

284

Page 285: code writing.pdf

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

Page 286: code writing.pdf

• 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

Page 287: code writing.pdf

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

Page 288: code writing.pdf

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

Page 289: code writing.pdf

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

Page 290: code writing.pdf

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_attendentENDCLASS. "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_passengerENDCLASS. "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

Page 291: code writing.pdf

passenger1->call_flight_attendent( ). passenger2->call_flight_attendent( ). ENDMETHOD. "mainENDCLASS. "lcl_example IMPLEMENTATION

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

Following is the output of the above code listing.

291

Page 292: code writing.pdf

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

Page 293: code writing.pdf

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

Page 294: code writing.pdf

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

Page 295: code writing.pdf

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

Page 296: code writing.pdf

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

Page 297: code writing.pdf

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

Page 298: code writing.pdf

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

Page 299: code writing.pdf

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

Page 300: code writing.pdf

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

Page 301: code writing.pdf

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

Page 302: code writing.pdf

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

Page 303: code writing.pdf

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

Page 304: code writing.pdf

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. "displayENDCLASS. "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

Page 305: code writing.pdf

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

Page 306: code writing.pdf

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

Page 307: code writing.pdf

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

Page 308: code writing.pdf

[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

Page 309: code writing.pdf

ENDMETHOD. "mainENDCLASS. "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

Page 310: code writing.pdf

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

Page 311: code writing.pdf

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

Page 312: code writing.pdf

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_semantics=>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. "mainENDCLASS. "lcl_example IMPLEMENTATIONSTART-OF-SELECTION. lcl_example=>main( ).

Following is the output of above code listing.

312

Page 313: code writing.pdf

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

Page 314: code writing.pdf

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. "mainENDCLASS. "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

Page 315: code writing.pdf

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

Page 316: code writing.pdf

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

Page 317: code writing.pdf

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

Page 318: code writing.pdf

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

Page 319: code writing.pdf

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. "mainENDCLASS. "lcl_example IMPLEMENTATION

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

After execution the following output is produced.

319

Page 320: code writing.pdf

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

Page 321: code writing.pdf

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

Page 322: code writing.pdf

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 = '"500"' token2 = '"Five Hunderd"'. CATCH zcx_exception_example_t100 INTO err_ref. MESSAGE err_ref TYPE 'I' DISPLAY LIKE 'E'. ENDTRY. ENDMETHOD. "mainENDCLASS. "lcl_example IMPLEMENTATION

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

Following is the output of above code listing.

322

Page 323: code writing.pdf

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

Page 324: code writing.pdf

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. "mainENDCLASS. "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

Page 325: code writing.pdf

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

Page 326: code writing.pdf

idenominator = 0 IMPORTING eresult = result ). ENDMETHOD. "divideENDCLASS. "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

Page 327: code writing.pdf

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. "divideENDCLASS. "lcl_example IMPLEMENTATION

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

Following output is produced after the execution of above report.

327

Page 328: code writing.pdf

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

Page 329: code writing.pdf

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

Page 330: code writing.pdf

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

Page 331: code writing.pdf

On activation tab leave default values and click Save.

331

Page 332: code writing.pdf

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. "mainENDCLASS. "lcl_example IMPLEMENTATION

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

332

Page 333: code writing.pdf

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

Page 334: code writing.pdf

334


Recommended