TAW12 ABAP Workbench Concepts part I
.
.
PARTICIPANT HANDBOOK INSTRUCTOR-LED TRAINING . Course Version: 15 Course Duration: 5 Day(s) Material Number: 50129723
SAP Copyrights and Trademarks
© 2015 SAP SE. All rights reserved.
No part of this publication may be reproduced or transmitted in any form or for any purpose without the express permission of SAP SE. The information contained herein may be changed without prior notice. Some software products marketed by SAP SE and its distributors contain proprietary software components of other software vendors. ●
Microsoft, Windows, Excel, Outlook, and PowerPoint are registered trademarks of Microsoft Corporation.
●
IBM, DB2, DB2 Universal Database, System i, System i5, System p, System p5, System x, System z, System z10, System z9, z10, z9, iSeries, pSeries, xSeries, zSeries, eServer, z/VM, z/OS, i5/OS, S/390, OS/390, OS/400, AS/400, S/390 Parallel Enterprise Server, PowerVM, Power Architecture, POWER6+, POWER6, POWER5+, POWER5, POWER, OpenPower, PowerPC, BatchPipes, BladeCenter, System Storage, GPFS, HACMP, RETAIN, DB2 Connect, RACF, Redbooks, OS/2, Parallel Sysplex, MVS/ESA, AIX, Intelligent Miner, WebSphere, Netfinity, Tivoli and Informix are trademarks or registered trademarks of IBM Corporation.
●
Linux is the registered trademark of Linus Torvalds in the U.S. and other countries.
●
Adobe, the Adobe logo, Acrobat, PostScript, and Reader are either trademarks or registered trademarks of Adobe Systems Incorporated in the United States and/or other countries.
●
Oracle is a registered trademark of Oracle Corporation
●
UNIX, X/Open, OSF/1, and Motif are registered trademarks of the Open Group.
●
Citrix, ICA, Program Neighborhood, MetaFrame, WinFrame, VideoFrame, and MultiWin are trademarks or registered trademarks of Citrix Systems, Inc.
●
HTML, XML, XHTML and W3C are trademarks or registered trademarks of W3C®, World Wide Web Consortium, Massachusetts Institute of Technology.
●
●
Java is a registered trademark of Sun Microsystems, Inc. JavaScript is a registered trademark of Sun Microsystems, Inc., used under license for technology invented and implemented by Netscape.
●
SAP, R/3, SAP NetWeaver, Duet, PartnerEdge, ByDesign, SAP BusinessObjects Explorer, StreamWork, and other SAP products and services mentioned herein as well as their respective logos are trademarks or registered trademarks of SAP SE in Germany and other countries.
●
Business Objects and the Business Objects logo, BusinessObjects, Crystal Reports, Crystal Decisions, Web Intelligence, Xcelsius, and other Business Objects products and services mentioned herein as well as their respective logos are trademarks or registered trademarks of Business Objects Software Ltd. Business Objects is an SAP company.
●
Sybase and Adaptive Server, iAnywhere, Sybase 365, SQL Anywhere, and other Sybase products and services mentioned herein as well as their respective logos are trademarks or registered trademarks of Sybase, Inc. Sybase is an SAP company.
All other product and service names mentioned are the trademarks of their respective companies. Data contained in this document serves informational purposes only. National product specifications may vary. These materials are subject to change without notice. These materials are provided by SAP SE and its affiliated companies ("SAP Group") for informational purposes only, without representation or warranty of any kind, and SAP Group shall not be liable for errors or omissions with respect to the materials. The only warranties for SAP Group products and services are those that are set forth in the express warranty statements accompanying such products and services, if any. Nothing herein should be construed as constituting an additional warranty.
© Copyright. All rights reserved.
iii
iv
© Copyright. All rights reserved.
Typographic Conventions American English is the standard used in this handbook. The following typographic conventions are also used.
This information is displayed in the instructor’s presentation
Demonstration
Procedure
Warning or Caution
Hint
Related or Additional Information
Facilitated Discussion
User interface control
Example text
Window title
Example text
© Copyright. All rights reserved.
v
vi
© Copyright. All rights reserved.
Contents xi
Course Overview
1
Unit 1:
2 13
Introduction to Object-Oriented Programming Lesson: Explaining the Object-Oriented Programming Model Lesson: Analyzing and Designing with Unified Modeling Language (UML)
23 33
Exercise 1: Create UML Diagrams Unit 2:
35 47 54 59 63 69 75 79 87 89 105
Lesson: Creating Local Classes Exercise 2: Create Local Classes Lesson: Creating Objects Exercise 3: Create Objects Lesson: Accessing Methods and Attributes Exercise 4: Call Methods Lesson: Implementing Constructors in Local Classes Exercise 5: Create and Use Constructors Lesson: Implementing Class Constructors in Local Classes Exercise 6: Create and Use Static Constructors Unit 3:
106 115 125 127 132 137 144 147 161 162 167 177 181 188 191
Fundamental Object-Oriented Syntax
Inheritance and Casting Lesson: Implementing Inheritance Exercise 7: Implement Inheritance Lesson: Implementing Upcasts Using Inheritance Exercise 8: Implement Upcasts Lesson: Implementing Polymorphism Using Inheritance Exercise 9: Implement Polymorphism Using Inheritance Lesson: Implementing Downcasts Using Inheritance Exercise 10: Implement Downcasts
Unit 4:
Interfaces and Casting Lesson: Defining and Implementing Local Interfaces Exercise 11: Define and Implement a Local Interface Lesson: Implementing Polymorphism Using Interfaces Exercise 12: Implement Polymorphism Using Interfaces Lesson: Integrating Class Models Using Interfaces Exercise 13: Integrate Class Models Using Interfaces
© Copyright. All rights reserved.
vii
209
Unit 5:
210 219 232
Lesson: Implementing Events in Local Classes Exercise 14: Implement Events in Local Classes Lesson: Implementing Events in Local Interfaces
233 247
Exercise 15: Implement Handling of Interface Events Unit 6:
Object-Oriented Repository Objects
248 257 267
Lesson: Creating Global Classes Exercise 16: Implement a Global Class Lesson: Defining and Implementing Global Interfaces
271 282
Exercise 17: Import and Implement a Global Interface Lesson: Implementing Inheritance in Global Classes
291
Unit 7:
292 299 305 314 325
381
Unit 8:
422 439
Class-Based Exceptions Lesson: Explaining Class-Based Exceptions Lesson: Defining and Raising Exceptions Exercise 20: Implement Class-Based Exceptions Lesson: Implementing Advanced Exception Handling Techniques Exercise 21: Map Exceptions to Each Other
Unit 9:
382 389 393 402 405 421
ABAP Object-Oriented Examples Lesson: Using the ABAP List Viewer (ALV) Exercise 18: Implement the ALV Grid Control Exercise 19: Implement a Dialog Box with the ALV Grid Control Lesson: Describing Business Add-Ins (BAdIs)
326 332 341 355 363
viii
Object-Oriented Events
Object-Oriented Design Patterns Lesson: Implementing Advanced Object-Oriented Techniques Lesson: Implementing the Singleton Pattern Exercise 22: Implement the Singleton Pattern Lesson: Implementing Factory Classes Using Friendship Exercise 23: Implement a Factory Class Using Friendship
Unit 10:
Program Calls and Memory Management Lesson: Using Shared Objects Exercise 24: Use Shared Objects
© Copyright. All rights reserved.
453
Unit 11:
Dynamic Programming
454 461
Lesson: Using Generic Data Types Exercise 25: Use Dynamically Typed Field Symbols in Dynamic SQL Statements
471 481
Exercise 26: Access Structure Components Dynamically Lesson: Describing Data Types, Data Objects, and Objects at Runtime Exercise 27: Provide Column Headers Using RTTI Lesson: Creating Data Types, Data Objects, and Objects at Runtime Exercise 28: Create Data Objects at Runtime Exercise 29: Create Data Types at Runtime with RTTC
493 505 511 521
© Copyright. All rights reserved.
ix
x
© Copyright. All rights reserved.
Course Overview
TARGET AUDIENCE This course is intended for the following audiences: ●
Application Consultant
●
Development Consultant
●
Developer
© Copyright. All rights reserved.
xi
xii
© Copyright. All rights reserved.
UNIT 1
Introduction to Object-Oriented Programming
Lesson 1 Explaining the Object-Oriented Programming Model
2
Lesson 2 Analyzing and Designing with Unified Modeling Language (UML) Exercise 1: Create UML Diagrams
13 23
UNIT OBJECTIVES ●
Describe the differences between the procedural and object-oriented programming models
●
Classify objects
●
Model in UML
© Copyright. All rights reserved.
1
Unit 1 Lesson 1 Explaining the Object-Oriented Programming Model
LESSON OVERVIEW This lesson provides an overview of the key concepts of ABAP programming using the objectoriented model. Business Example You need to explain the object-oriented programming model and its advantages to your development project manager. For this reason, you require the following knowledge: ●
An understanding of procedural and object-oriented programming
●
An understanding of ABAP objects
LESSON OBJECTIVES After completing this lesson, you will be able to: ●
Describe the differences between the procedural and object-oriented programming models
Evolution of ABAP
Figure 1: History of Selected Programming Languages
As you can see from the figure History of Selected Programming Languages, object-oriented programming (like the Simula 67 programming language), and the logical and procedural programming models (as used in languages like C and Pascal), were developed at about the
2
© Copyright. All rights reserved.
Lesson: Explaining the Object-Oriented Programming Model
same time. Previously, COBOL and the procedural programming model dominated enterprise application development. SAP used a macro assembler before ABAP was created. Even today, many developers have more experience with procedural programming than with object-oriented programming. Therefore, this introduction references the procedural model when it explains object-oriented programming. ABAP was created to improve reporting. It was independently developed as an in-house programming language. It was influenced by other programming languages like COBOL and Pascal. ABAP was then extended to form ABAP Objects. Therefore, ABAP Objects unites object-oriented and procedural elements in one programming language. For the objectoriented programming part, ABAP Objects adopted object-oriented concepts for enterprise application development in other languages (for example, Java, C++, and Smalltalk).
The Procedural Programming Model
Figure 2: Characteristics of the Procedural Programming Model
Global variables for a program contain data, while subroutines contain functions. Every subroutine can access all global variables.
© Copyright. All rights reserved.
3
Unit 1: Introduction to Object-Oriented Programming
Components of a Procedural ABAP Program
Figure 3: Typical Procedural ABAP Program
A typical procedural ABAP program consists of type definitions and data declarations. The data declarations describe the data structure the program uses when being executed. It is possible to encapsulate logic in modularization units (for example, subroutines or function modules). However, at the main program level, there is no special protection for the global data objects. It is possible to read and change global variables from anywhere in the program. Encapsulation of Data Using Function Groups
Figure 4: Encapsulating Data Using Function Groups
When a function module is called in the main program, its function group is loaded into the internal session. The function group remains active until the main program finishes executing. The system stores the main program and the called function groups in separate memory
4
© Copyright. All rights reserved.
Lesson: Explaining the Object-Oriented Programming Model
areas. Even if the data objects of the function groups have the same data object names as they do in the calling program, they do not share the same memory space. Nothing is shared, even if the data objects of the function groups have the same name. It is not possible to access the global data of a function group directly from the main program. You can only call the function modules of the function groups from the main program. In turn, the function modules can access other components, particularly the global data of their own function group. Encapsulation also uses the idea that the implementation of a service can be hidden from other components of the system. The reason for this is that the other components cannot and do not need to make assumptions about the internal status of the modularization unit. In this way, the design of these other components is not dependent on the other modularization units being implemented in a specific way. A function group brings together data and functions which manage the data. Encapsulated access to data and services is one of the many concepts of the object-oriented programming model. Therefore, this programming model and the procedural part of ABAP Objects support this encapsulation. When implementing the Business Application Programming Interface (BAPI), BAPIs are implemented as function modules and Business Objects are implemented as function groups. Function Groups
Figure 5: Example of a Function Group
The function group S_VEHICLE provides a user or client with the services Inc_speed, dec_speed, and get_speed. These services are the interface of the function group. They all have access to the global data object speed, which belongs to the function group.
© Copyright. All rights reserved.
5
Unit 1: Introduction to Object-Oriented Programming
Example of Using the Function Group
Figure 6: Example of Using the Function Group
The main program cannot access the data object speed of the function group directly.
Multiple Instantiation
Figure 7: Several Instances of One Function Group
In order for the main program to work with several vehicles, there must be additional programming and administrative effort. A function group can only refer to one vehicle at a time.
6
© Copyright. All rights reserved.
Lesson: Explaining the Object-Oriented Programming Model
Multiple Instantiation in Object-Oriented Programming
Figure 8: Multiple Instantiation in Object-Oriented Programming
The possibility to create several runtime instances using the same program context is one of the key characteristics of object-oriented programming. In this example, you will develop a program to create four vehicles, all of which have different characteristics. However, all the vehicles share the same data structure and the same set of functions. They all have the ability to protect their data from outside access. ABAP Main Memory and Encapsulation
Figure 9: ABAP Main Memory and Encapsulation
The features of encapsulation using function groups and subroutines are as follows: ●
You use modularization units to encapsulate functions and data.
●
You can work with the global data of the main program.
The features of encapsulation using objects are as follows: ●
You can use objects to encapsulate functions and data.
© Copyright. All rights reserved.
7
Unit 1: Introduction to Object-Oriented Programming
●
You can create multiple instances (objects).
You can perform multiple instantiation. Objects are stored in the same internal session as the program in use. All data areas are separate from each other, which keeps them protected. Data Management in Procedural and Object-Oriented Models
Figure 10: Data Management in Procedural and Object-Oriented Models
Unlike in procedural programming, using multiple instantiation in object-oriented programming allows you to create a direct abstraction of a real object. Encapsulation was systematically extended in this programming model.
ABAP Objects The object-oriented concepts of ABAP Objects share concepts with other modern objectoriented languages like C++ or Java. Concepts that proved to be unsuccessful in other languages were not included in ABAP Objects. On the other hand, ABAP Objects has helpful language elements that C++ and Java do not have. Certain features of ABAP Objects only exist because of the guaranteed upward compatibility of older ABAP language elements. The difference in ABAP Objects compared to other object-oriented languages are in the development environment. You can use the entire range of functions of the ABAP Workbench with ABAP Objects. You can use ABAP Objects statements in procedural ABAP programs.
8
© Copyright. All rights reserved.
Lesson: Explaining the Object-Oriented Programming Model
ABAP Objects as a Compatible Extension of ABAP
Figure 11: ABAP Objects as a Compatible Extension of ABAP
ABAP Objects is not a new language, but it was designed as a systematic extension of ABAP. All of the extensions, including the old procedural parts, are upward compatible. Type checks in the object-oriented contexts of ABAP Objects are stricter than those in the procedural contexts. To develop ABAP Objects, SAP cleaned up the ABAP language in the object-oriented contexts. This means that obsolete statements lead to syntax errors.
Note: However, it is also advisable to avoid obsolete statements in the purely procedural environment, since it creates safer and more flexible source code. Nevertheless, because the language is upward compatible, it is not possible to prevent the use of such statements entirely. For a list of obsolete language elements, refer to the ABAP keyword documentation. ABAP prohibits the use of obsolete statements in the object-oriented context.
© Copyright. All rights reserved.
9
Unit 1: Introduction to Object-Oriented Programming
Client/Server Relationship Between Objects
Figure 12: Client/Server Relationships Between Objects
Objects behave like client/server systems. When one object sends a message to another object to ask it to behave in a certain way, the first object is defined as a client and the second object is defined as a server. To be able to separate requests and deliveries of services, the following conditions must be met: ●
●
The client object must adhere to the protocol of the server object. The protocol of server object must be clear enough for a potential client to follow it without any problems.
Objects can perform both roles simultaneously. They can offer services to other objects while requesting services at the same time. In object-oriented programming, the services are distributed among the objects in such a way that there are no redundancies and each object offers exactly those services it is responsible for. If an object needs any other services, it requests them from other objects. This concept is known as the principle of delegation. Client/Server Relationship-Example The developer should implement the common task of data retrieval and output over two objects. One object is responsible for data retrieval and another object is responsible for output. As long as the data retrieval object does not change its protocol, the developer can alter the retrieval object’s internal implementation without changing the other object. Alternatively, a different object could even replace the data retrieval object as long as the new object uses the same protocol. These exchanges can also take place at runtime.
10
© Copyright. All rights reserved.
Lesson: Explaining the Object-Oriented Programming Model
Additional Concepts of the Object-Oriented Programming Model
Figure 13: Additional Concepts of the Object-Oriented Programming Model
Some additional concepts in the object-oriented programming model are as follows: ●
Inheritance Inheritance defines the implementation relationships between classes, so that one class (subclass) adopts, adapts, or extends the structure and behavior of another class (superclass).
●
Polymorphism Polymorphism is when instances of classes respond differently to the same messages.
●
Event control Instead of sending messages directly to specific objects, objects can also trigger events. Then other objects react when the event is triggered.
Object-Oriented ABAP Key Characteristics of the Object-Oriented Programming Model of ABAP Objects ●
Objects are a direct abstraction of the real world.
●
Objects are units made up of data and functions.
●
Processes can be implemented in a better way than in procedural programming.
Advantages of the Object-Oriented Programming Model Compared to the Procedural Programming Model ●
Improved software structure and consistency in the development process
●
Reduced maintenance effort and less susceptibility to errors
●
Better integration of the customer or user into the analysis, design, and maintenance process
© Copyright. All rights reserved.
11
Unit 1: Introduction to Object-Oriented Programming
●
Simpler and more secure extension of the software
A standardized language is used in the various phases of software development (analysis, specification, design, and implementation). Because of this standardization, communication is easier when you change between phases. The Software Development Process
Figure 14: The Software Development Process
In object-oriented programming, analysis and design decisions have a greater effect on the implementation than they have on procedural programming. Therefore, use modeling language or tools to standardize the analysis and design phase. LESSON SUMMARY You should now be able to: ●
12
Describe the differences between the procedural and object-oriented programming models
© Copyright. All rights reserved.
Unit 1 Lesson 2 Analyzing and Designing with Unified Modeling Language (UML)
LESSON OVERVIEW This lesson explains how to develop an object-oriented solution to a business application problem. It also explains how to classify your objects and define the relationships between them using parts of Unified Modeling Language (UML) as a visual aid. Business Example You need to model a business application requirement before you implement the business application. For this reason, you require the following knowledge: ●
An understanding of class diagrams
●
An understanding of object diagrams
●
An understanding of sequence diagrams
LESSON OBJECTIVES After completing this lesson, you will be able to: ●
Classify objects
●
Model in UML
Classification of Objects
Figure 15: Classifying Objects
© Copyright. All rights reserved.
13
Unit 1: Introduction to Object-Oriented Programming
Object-oriented programming views the real world as a collection of objects like airplanes, cars, and people. Some of these objects are similar. In other words, objects can be described in the same way if they use the same characteristics and exhibit the same behavior. You can group all the characteristics and behaviors of these similar objects into one central class. This class is used to describe every object derived from it. Therefore, a class is a description of a quantity of objects that exhibit the same characteristics and the same behavior. For example, the vehicle (make x, ..., model n), is an object of class car. This object is a concrete instance of its class. Therefore, an object has an identity, a status (number of characteristic instances), and a behavior. The concepts of identity and status are different from one another. Identity is an attribute that distinguishes each object from all the other objects in its class. Two objects can have identical attribute values, but these objects may not be identical . For example, two coffee cups have the same height, diameter, handle, and color. Although their statuses are completely identical, they are two different coffee cups. Literature on the subject of object-oriented programming talks about instances. The term instance means an object.
Note: The literal meaning of instance is slightly more specific. It means that the instance of a class is uniquely identifiable. In this chapter, you will make a distinction between instance and object. Classes as Abstraction Forms
Figure 16: Classes as Abstraction Forms
In a software context, abstractions are simplifications of complex relationships in the real world. You can abstract a real, existing object to the dimensions needed to simulate a certain section of the real world. In the figure Classes as Abstraction Forms, vehicles are used to explain the concept of abstraction. Software for a vehicle enthusiast and software for a scrap merchant contain different abstractions (classes) for objects. Therefore, depending on the type of abstraction, a class can contain different aspects of an object.
14
© Copyright. All rights reserved.
Lesson: Analyzing and Designing with Unified Modeling Language (UML)
Comparing Classes and Objects
Figure 17: Comparing Classes and Objects
An understanding of the relationship between classes and objects is a prerequisite for completing the following lessons successfully. Modeling in UML UML is a globally standardized modeling language. You use it for the specification, construction, visualization, and documentation of software system models. UML enables uniform communication between users. UML is an industry standard and was developed by the Object Management Group (OMG) in September 1997. SAP uses UML as the company-wide standard for object-oriented modeling. For more information on the UML specifications, see http://www.omg.org on the OMG homepage.
Class Diagrams The different diagram types in UML represent different views of a system. Three Diagram Types that Represent Different Views of a System ●
Class diagrams Class diagrams show the relationships between the classes. This is a static view of a model.
●
Behavior diagrams Behavior diagrams show the sequence in which the objects relate to each other.
●
Component diagrams Component diagrams show the organization and dependencies of components.
You can use ABAP Objects to implement class diagrams and behavior diagrams from a programming perspective.
© Copyright. All rights reserved.
15
Unit 1: Introduction to Object-Oriented Programming
Component diagrams can be realized using the repository object package. UML Representation of a Class
Figure 18: Representation of a Class
A class is represented by a rectangle in UML notation. A class can be represented as follows: ●
Name of the class
●
Attributes of the class (optional)
●
Methods of the class (optional)
Attributes describe the data that can be stored in the objects of a class. They also determine the status of an object. Methods describe the functions an object can perform. They determine how an object behaves. Example of a Class Diagram
Figure 19: An Example of a Class Diagram
16
© Copyright. All rights reserved.
Lesson: Analyzing and Designing with Unified Modeling Language (UML)
A class diagram describes all static relationships between the classes. The basic forms of static relationships are as follows: Association A customer books a car at a rental car company. Generalization and Specialization A car, a bus, and a truck are all vehicles.
Note: Classes can also be shown in class diagrams with their attributes and methods. In this example of a class diagram, these attributes and methods have been omitted to improve clarity. Association
Figure 20: Association
An association describes a semantic relationship between classes. The specific relationship between objects in these classes is known as an object link. Therefore, object links indicate associations. However, an association can also be recursive. In that case, the class would have a relationship with itself. In most cases, recursive associations are used to link two different objects in the same class. Each association has two roles--one for each direction of the association. Each role can be described by an association name. Each role has a cardinality that shows how many instances can participate in this relationship. The multiplicity is the number of participating objects in one class that have a relationship to an object in the other class. Like all other elements of the model, cardinalities are dependent on the concrete situation being modeled. In this example, you could also require a cardinality of at least one to indicate that only someone who actually makes a booking becomes a customer of the rental car company. On
© Copyright. All rights reserved.
17
Unit 1: Introduction to Object-Oriented Programming
the other hand, the cardinality of any number would allow for a more general definition of a customer. Characteristics of association are as follows: ●
●
●
●
●
Represent an association between class symbols by drawing a line between them. Specify the cardinality (also referred to as multiplicity) of the relationship at the end of each line. You must use arrows to indicate the navigation options. You must write the association name in italics above the line. The name may contain an arrow to indicate the read direction. Enter the role names at the end of the lines if the modeler defines roles for both partners.
Association with Roles-Example
Figure 21: Examples of Association with Roles
You can use role names at the end of the of the association lines to describe the relationships between the classes involved. In the figure Examples of Association with Roles, a person could appear in the role of an employee or in the role of a company director. In the recursive association shown in the figure, Examples of Association with Roles, the roles of child and parent are defined using role names. Two instances of the LCL_PERSON class have a relationship with each other and represent two roles.
18
© Copyright. All rights reserved.
Lesson: Analyzing and Designing with Unified Modeling Language (UML)
Association Classes
Figure 22: Association Classes
If association is used to link two classes, then a special class can represent this relationship. The characteristics of the relationship are described using the attributes of the association class. A dotted line connects this class to the association line. Aggregation and Composition
Figure 23: Aggregation and Composition
Aggregation and composition are specializations of association. Aggregation and composition show that an object can contain other objects. The relationship can be described using the phrases “consists of” or “is a part of”. For example, a car consists of wheels and an engine among other things. Aggregation and composition appear as a line between two classes. They are labelled using a small rhombus. The rhombus indicates the aggregation or composition. Otherwise, the notation conventions are the same used for associations. Composition is a specialization of aggregation. Composition means the contained object cannot exist without the aggregation (for example, a car reservation cannot exist without the
© Copyright. All rights reserved.
19
Unit 1: Introduction to Object-Oriented Programming
car rental agency). Therefore, the cardinality of this kind of aggregate is at least one. The lifetime of the individual parts is linked to the lifetime of the aggregate. This means parts are created either at the same time as the aggregate or after the aggregate, and are destroyed either at the same time as the aggregate or before the aggregate. In UML notation, a filled-in rhombus denotes composition. Generalization and Specialization
Figure 24: Generalization and Specialization
Generalization and specialization relationships are always bidirectional. For example, the class lcl_truck can be generalized as a special class of lcl_vehicle. Generalization and specialization relationships are denoted by a triangular arrow. This arrow always points from the specialized class to the generalized class. The level of generalization increases in the direction of the arrow. Trees can be built up using these relationships.
20
© Copyright. All rights reserved.
Lesson: Analyzing and Designing with Unified Modeling Language (UML)
Object Diagrams
Figure 25: An Object Diagram
An object diagram is a snapshot taken during program execution. It describes instances of classes and the relationships between them. It is not a new type of diagram, but rather a variant of the class diagram. It is only useful for representing a complex class diagram.
Sequence Diagrams
Figure 26: A Sequence Diagram
Sequence diagrams are used to show certain processes or situations. A sequence diagram describes the sequence in which objects are processed and the interaction they have with each other. Sequence diagrams may show the following processes: ●
When objects are created or deleted
© Copyright. All rights reserved.
21
Unit 1: Introduction to Object-Oriented Programming
●
When objects exchange messages
In UML notation, the object lifeline is represented by dotted vertical lines with a box containing the object name at the top. An X is used to indicate the end of the lifeline. The control focus appears as a vertical rectangle on the object lifeline. The control focus shows the active period of the object. Possible statuses of an object are as follows: ●
An object is active when actions are executed.
●
An object is indirectly active if it is waiting for a subordinate procedure to end.
Messages appear as horizontal arrows between the object lines. The message is written above the arrow in the Message (parameter) form. There are various ways to represent the reply. In this example, it appears as a dotted returning arrow. You can also include a description of the process and add comments to the object lifeline. The Delegation Principle
Figure 27: Delegation Principle in Sequence Diagram
In delegation, two objects are involved in handling a request. The recipient of the request assigns the execution of the request to a delegate. In this example, the driver (object driver) sends the message get_fuel_level ( ) to the vehicle (object car). When the message is received, the car sends a message to the tank (object tank) to find out what the tank contains. In other words, the car delegates the task to the tank. If necessary, the car formats the information containing the current value of the contents of the tank before passing it back to the driver.
22
© Copyright. All rights reserved.
Unit 1 Exercise 1 Create UML Diagrams
Business Example You are a modeler for an airline corporation that owns several airline carriers. You need to create a simple model to manage your airline carriers and airplanes. For this reason, you must be able to design simple UML class diagrams and model the basic objects. In this airplane management model, you need to create relevant classes with attributes and methods, and define the association between classes using suitable association types and cardinalities. Create a Class Diagram 1. Create a UML class diagram containing the following classes: Table 1: Classes Class Name
Description
LCL_CARRIER
For the Airline Companies
LCL_AIRPLANE
For Airplanes (unspecific)
LCL_PASSENGER_PLANE
For Passenger Planes
LCL_CARGO_PLANE
For Cargo Planes
2. Create appropriate attributes and methods for each class. 3. Define relationships between your classes and choose suitable association types. 4. Choose suitable cardinalities. Distinguish Between Classes and Objects As a modeler, decide whether the object diagrams in this unit are correct. 1. The figures Possible Object Diagrams (1) and Possible Object Diagrams (2) show a class diagram. Eight object diagrams are drawn for this class diagram. Decide whether each object diagram is correct and mark the corresponding checkbox to indicate your answer.
© Copyright. All rights reserved.
23
Unit 1: Introduction to Object-Oriented Programming
Figure 29: Possible Object Diagrams (1)
Figure 30: Possible Object Diagrams (2)
24
© Copyright. All rights reserved.
Unit 1 Solution 1 Create UML Diagrams
Business Example You are a modeler for an airline corporation that owns several airline carriers. You need to create a simple model to manage your airline carriers and airplanes. For this reason, you must be able to design simple UML class diagrams and model the basic objects. In this airplane management model, you need to create relevant classes with attributes and methods, and define the association between classes using suitable association types and cardinalities. Create a Class Diagram 1. Create a UML class diagram containing the following classes: Table 1: Classes Class Name
Description
LCL_CARRIER
For the Airline Companies
LCL_AIRPLANE
For Airplanes (unspecific)
LCL_PASSENGER_PLANE
For Passenger Planes
LCL_CARGO_PLANE
For Cargo Planes
a) Use the model solution in the figure Class Diagram for Exercise - CARRIER/AIRPLANE as a guide. 2. Create appropriate attributes and methods for each class. a) Be sure to define the general attributes and methods for airplanes in LCL_AIRPLANE. b) Use the model solution as a guide for the attributes and methods for all of the classes required. 3. Define relationships between your classes and choose suitable association types. a) A generalization and specialization relationship between LCL_AIRPLANE and LCL_PASSENGER_PLANE or LCL_CARGO_PLANE seems to be appropriate. Create an aggregation between LCL_AIRPLANE and LCL_CARRIER. b) Use the model solution as a guide. 4. Choose suitable cardinalities. a) You can use various cardinalities in this case. Use the relevant sections of the lesson and the model solution as a guide.
© Copyright. All rights reserved.
25
Unit 1: Introduction to Object-Oriented Programming
Figure 28: Class Diagram for Exercise - CARRIER/AIRPLANE
Distinguish Between Classes and Objects As a modeler, decide whether the object diagrams in this unit are correct. 1. The figures Possible Object Diagrams (1) and Possible Object Diagrams (2) show a class diagram. Eight object diagrams are drawn for this class diagram. Decide whether each object diagram is correct and mark the corresponding checkbox to indicate your answer.
Figure 29: Possible Object Diagrams (1)
26
© Copyright. All rights reserved.
Lesson: Analyzing and Designing with Unified Modeling Language (UML)
Figure 30: Possible Object Diagrams (2)
a) The object diagrams numbered 2, 4, 5, 6, and 8 are correct.
© Copyright. All rights reserved.
27
Unit 1: Introduction to Object-Oriented Programming
LESSON SUMMARY You should now be able to:
28
●
Classify objects
●
Model in UML
© Copyright. All rights reserved.
Unit 1 Learning Assessment
1. Data and functions are kept separate in the procedural programming model. Determine whether this statement is true or false. X
True
X
False
2. What does multiple instantiation mean? Choose the correct answer. X
A Creating and managing runtime instances
X
B Implementing relationships between classes
X
C Creating instances of different classes
X
D Sending messages directly to specific objects by triggering events
3. Which of the following is a simplification of complex relationships in the real world? Choose the correct answer. X
A Inheritance
X
B Abstraction
X
C Encapsulation
X
D Event control
4. Which kind of UML diagram pays particular attention to the sequence in which objects relate to each other? Choose the correct answer. X
A class
X
B behavior
X
C component
X
D object
© Copyright. All rights reserved.
29
Unit 1: Learning Assessment
5. You can group all characteristics and behaviors of similar objects into one central class. Determine whether this statement is true or false.
30
X
True
X
False
© Copyright. All rights reserved.
Unit 1 Learning Assessment - Answers
1. Data and functions are kept separate in the procedural programming model. Determine whether this statement is true or false. X
True
X
False
2. What does multiple instantiation mean? Choose the correct answer. X
A Creating and managing runtime instances
X
B Implementing relationships between classes
X
C Creating instances of different classes
X
D Sending messages directly to specific objects by triggering events
3. Which of the following is a simplification of complex relationships in the real world? Choose the correct answer. X
A Inheritance
X
B Abstraction
X
C Encapsulation
X
D Event control
© Copyright. All rights reserved.
31
Unit 1: Learning Assessment - Answers
4. Which kind of UML diagram pays particular attention to the sequence in which objects relate to each other? Choose the correct answer. X
A class
X
B behavior
X
C component
X
D object
5. You can group all characteristics and behaviors of similar objects into one central class. Determine whether this statement is true or false.
32
X
True
X
False
© Copyright. All rights reserved.
UNIT 2
Fundamental Object-Oriented Syntax
Lesson 1 Creating Local Classes Exercise 2: Create Local Classes
35 47
Lesson 2 Creating Objects Exercise 3: Create Objects
54 59
Lesson 3 Accessing Methods and Attributes Exercise 4: Call Methods
63 69
Lesson 4 Implementing Constructors in Local Classes Exercise 5: Create and Use Constructors
75 79
Lesson 5 Implementing Class Constructors in Local Classes Exercise 6: Create and Use Static Constructors
87 89
UNIT OBJECTIVES ●
Define local classes
●
Define attributes
●
Create methods
●
Create objects
●
Call instance methods
●
Call static methods
●
Call functional methods
●
Access public attributes
© Copyright. All rights reserved.
33
Unit 2: Fundamental Object-Oriented Syntax
34
●
Create and use constructors
●
Create and use static constructors
© Copyright. All rights reserved.
Unit 2 Lesson 1 Creating Local Classes
LESSON OVERVIEW This lesson provides an overview of local classes, attributes, and methods, which are the fundamental object-oriented syntax elements. Business Example As a developer, you need to implement classes, objects, and associations of your model in ABAP Objects. LESSON OBJECTIVES After completing this lesson, you will be able to: ●
Define local classes
●
Define attributes
●
Create methods
Definition of Local Classes
Figure 31: An Example of a Class
The concept of classes is the foundation of object-oriented programming. A class can either have public components or private components. You can access public components, such as methods and events, from outside a class. However, you cannot access private components, for example data types and attributes, from outside a class.
© Copyright. All rights reserved.
35
Unit 2: Fundamental Object-Oriented Syntax
The figure An Example of a Class, shows a vehicle as an example of a class. Characteristics of a Class
Figure 32: Defining Classes
Characteristics of a class in object-oriented programming are as follows: ●
A class is a set of objects that have the same structure and exhibit the same behavior.
●
A class provides a blueprint for all objects based on this class.
●
●
A class is made up of components, such as attributes, methods, events, constants, types, and implemented interfaces, defined in the definition part. You can implement only methods in the implementation part. A class statement cannot be nested; that is, you cannot define a class within a class. However, you can define local auxiliary classes for global classes.
Declaration of Attributes
Figure 33: An Example of Attributes
Attributes contain the data that can be stored in the objects of a class. The types of class attributes are as follows:
36
© Copyright. All rights reserved.
Lesson: Creating Local Classes
●
Elementary data object
●
Structured
●
Table-type
Attributes can consist of data types (local or global) or reference types. Table 2: Attributes The following table shows some examples of attributes for class LCL_VEHICLE: Attributes
Description
MAKE
Vehicle make
MODEL
Type of model
SER_NO
Serial number
COLOR
Color
MAX_SEATS
Number of seats
R_MOTOR
Reference to class LCL_MOTOR
Definition of Attributes, Types, and Constants
Figure 34: Definition of Attributes, Types, and Constants
In class DATA statements, you can only use the TYPE addition to refer to data types. The LIKE addition is only allowed for local data objects or SY fields (for example, SY-DATE, SY-UNAME, and so on). The READ-ONLY addition indicates that a public attribute declared with DATA can be read from outside. However, the attribute can only be changed by methods in the same class. Currently, you can use the READ-ONLY addition in the public visibility section (PUBLIC SECTION) of a class declaration or in an interface definition. With TYPE REF TO, you can type an attribute as a reference.
© Copyright. All rights reserved.
37
Unit 2: Fundamental Object-Oriented Syntax
The CONSTANTS statement is used within the class definition to define data objects that have a constant value. If you use the TYPES statement in the class definition, you are declaring a local type which is specific to this local class. You can create a local type to be used by one or more attributes within the same class.
Visibility of Attributes
Figure 35: Visibility Sections of Attributes
Private attributes cannot be addressed directly from outside the class and are not visible to outside users. You can protect attributes from outside access by characterizing them as private attributes. Note: The friendship concept is an exception to this rule. Public attributes are attributes that are visible to all users and can be directly accessed by outside users. Similarly, the constants and types defined by a class can be either private (for use inside the class), or public, (accessible from outside the class). The public components of a class are collectively known as the class interface. Using the private visibility section is known as information hiding or encapsulation. Encapsulation protects a class user by making changes to private components invisible to the external user. You can change the private components of a class without changing the interface. Assume that the private components of a class are changed at some point with its interface remaining the same, external users can still continue to work with the class as before. The external users can only access the components through the interface of the class and will not notice the internal implementation changes in the PRIVATE SECTIONS. However, when the public components of a class change, every external user must take those changes into account.
38
© Copyright. All rights reserved.
Lesson: Creating Local Classes
Therefore, use public attributes sparingly, or avoid making incompatible changes to public components altogether. Accessing Private Attributes
Figure 36: Defining Attributes
Private attributes are defined in the PRIVATE SECTION of a class. Public attributes are defined in the PUBLIC SECTION of a class. You can access private attributes using public methods that return or change the values of the private attributes. The slightly higher runtime requirement (method calls in comparison with direct value assignment) is taken into account to satisfy the encapsulation concept. The signature of a public method clearly establishes which values must or can be transferred, and which types are to be assigned to these values. The signature of a public method forces the external user to use the correct types. This method also ensures that all private attributes are dealt consistently. For the example in the figure Defining Attributes, if the MAKE and MODEL attributes are public, it will be quite risky because the user may forget to supply the attributes or specify inconsistent attributes. To implement this situation, you can use a public method, SET_TYPE, to ensure that proper values are specified for both the attributes. A strict syntax check governs method calls, ensuring the transfer of all required parameters. A method can perform a consistency check (to see if a certain vehicle make produces the chosen model) and raise an exception if an error occurs. To minimize runtime, individual attributes can be defined in the public visibility section. After you have defined the attributes give them the READ-ONLY addition.
© Copyright. All rights reserved.
39
Unit 2: Fundamental Object-Oriented Syntax
Static Attributes and Instance Attributes
Figure 37: Comparison of Instance Attributes with Static Attributes
Different kinds of attributes are as follows: ●
Instance attributes Instance attributes exist once per object; that is, once per runtime instance of the class. You define instance attributes with the syntax element, DATA.
●
Static attributes Static attributes exist once for each class and are visible for all runtime instances in that class. You define static attributes with the syntax element, CLASS-DATA. Static attributes usually contain the following information that applies to all instances: -
Types and constants
-
Central application data buffers
-
Administrative information, such as the instance counter
Technical literature refers to static attributes as “class attributes” (we use the CLASS-DATA syntax element). As in C++ and Java, ABAP Objects uses the official term “static attribute”. Instance Attributes and Static Attributes in the Program Context
Figure 38: Instance Attributes and Static Attributes in the Program Context
40
© Copyright. All rights reserved.
Lesson: Creating Local Classes
The figure shows how the GV_N_O_VEHICLES static attribute is related to other program elements in the memory. The static attribute exists only once in the loaded class, regardless of the number of instances of LCL_VEHICLE. Therefore, you can say that instances share static attributes.
Caution: An integer data object is defined to count instances. It is not possible to find out the number of created instances from the system.
Implementation of Methods
Figure 39: Syntax for Methods
Some of the key characteristics of methods are as follows: ●
●
●
Methods are internal procedures in classes that determine the behavior of the objects. They can access all attributes in their class and can therefore change the state of attributes. Methods have a signature (interface parameters and exceptions) that enables them to receive values when they are called and pass values back to the calling program. Methods can have any number of IMPORTING, EXPORTING, and CHANGING parameters. All parameters can be passed by value or reference.
Method Signature Functional methods have one RETURNING parameter as well as importing parameters and exceptions. You can define all input parameters (IMPORTING and CHANGING parameters) as optional parameters in the declaration using the OPTIONAL or DEFAULT addition. You do not need to
© Copyright. All rights reserved.
41
Unit 2: Fundamental Object-Oriented Syntax
pass these parameters when you call the object. By using the OPTIONAL addition, the parameter initializes according to type, while the DEFAULT addition allows you to enter a start value. Methods also support the SY-SUBRC return value, but only when you define the signature exceptions with the use of EXCEPTIONS. Use the RAISING addition in place of EXCEPTIONS to propagate class-based exceptions. The caller then handles these class-based exceptions without evaluating the SY-SUBRC return value.
Note: Do not use both concepts together in one program.
Visibility of Methods
Figure 40: Visibility Sections of Methods
You assign methods to a visibility section to determine whether methods are called from outside the class or from within the class. Private methods allow internal modularization.
42
© Copyright. All rights reserved.
Lesson: Creating Local Classes
Access to Private Methods
Figure 41: Accessing Private Methods
You define private methods in the PRIVATE SECTION and public methods in the PUBLIC SECTION of a class. It is not possible to directly access private methods from outside. However, a private method can be called by a public method. In the figure, Accessing Private Methods, INIT_TYPE is a private method that is called by the SET_TYPE public method. Defining this private auxiliary method is useful because the instruction to initialize attributes may be used in other methods.
Note: This is an introductory example. Later, you will learn more programming techniques for evaluating formal parameters. In a class, declarations of attribute names, method names, event names, constant names, type names, and alias names share the same namespace. Additionally there is a local namespace within methods. Local declarations within a method override declarations made in the class.
© Copyright. All rights reserved.
43
Unit 2: Fundamental Object-Oriented Syntax
Static Methods and Instance Methods
Figure 42: Comparison of Instance Methods with Static Methods
Different kinds of methods are as follows: ●
Instance methods You define instance methods using the METHODS syntax keyword.
●
Static methods You define static methods using the CLASS-METHODS syntax keyword. You define static methods at class level. In their implementation, you can only access static components. This means that static methods do not need instances and can be directly accessed through the class.
In the example shown in the figure Comparison of Instance Methods with Static Methods, the static method GET_N_O_VEHICLES can only access the attribute GV_N_O_VEHICLES. The method set_type is an instance method and can access all the attributes, both static and instance. You may see static methods referred to as class methods, in line with the CLASS-METHODS keyword. In ABAP Objects, the official term is “static method”, as it is in C++ and Java.
44
© Copyright. All rights reserved.
Lesson: Creating Local Classes
Representation of Visibility in UML Class Diagrams
Figure 43: Visibility Sections and UML Notation
A UML class diagram lists the class name, class attributes, and methods. The components in a class are shown in a UML diagram using the following notations: ●
Plus sign (+) A plus sign (+) indicates public components (visible to all users).
●
Minus sign (–) A minus sign (–) indicates private components (invisible to outside users).
●
Underline An underlined component name sign (_) indicates static components.
Alternatively, the keywords public and private can be used as a prefix for methods. A UML also allows manufacturers of modeling tools to create their own symbols for increased visibility. The use of visibility characteristics is optional and is normally used only in models that are nearing implementation.
© Copyright. All rights reserved.
45
Unit 2: Fundamental Object-Oriented Syntax
46
© Copyright. All rights reserved.
Unit 2 Exercise 2 Create Local Classes
Business Example You are a developer for an airline corporation that owns several airline carriers. You need to develop an object-oriented program that can manage airline carriers and their airlines. For this reason, you must be able to define classes, attributes, and methods. Template None Solution SAPBC401_BAS_S1 Create a Program 1. Create an executable program, ZBC401_##_MAIN, without a TOP include. Note: In the exercises for this course, when the input values include ##, replace ## with your group number. Define and Implement a Local Class Declare and implement a class for airplanes. 1. Within your main program, declare the local class LCL_AIRPLANE. 2. Define the following attributes: Table 3: Attributes Attribute Name/description Data type
Attribute Type
MV_NAME (name of airplane)
STRING
Private instance attribute
MV_PLANETYPE (type of airplane)
SAPLANE-PLANETYPE
Private instance attribute
GV_N_O_AIRPLANES (instance counter)
I
Private static attribute
3. Define the public instance method SET_ATTRIBUTES for setting private instance attributes. Your method signature must consist of two suitable import parameters defined as compatible with the two attributes.
© Copyright. All rights reserved.
47
Unit 2: Fundamental Object-Oriented Syntax
4. Implement the public instance method SET_ATTRIBUTES in such a way that the two instance attributes are set. 5. Define the public instance method DISPLAY_ATTRIBUTES for displaying private instance attributes. 6. Implement the public instance method DISPLAY_ATTRIBUTES in such a way that the values of the two instance attributes are output as an ABAP list. You can also output icons from the type group ICON. Hint: From SAP NetWeaver 7.02, you no longer need to load type groups explicitly using the TYPE-POOLS statement. 7. Define the public static method DISPLAY_N_O_AIRPLANES to display the private static attribute. 8. Implement the public static method DISPLAY_N_O_AIRPLANES in such a way that the value of the static attributes is output in the ABAP list. Note: So far, your class does not have a mechanism for ensuring that the instance counter increases each time an object is created. Decide if you want to omit the counter for now, or if you want to temporarily control increments using the SET_ATTRIBUTES method. 9. To improve the list output, arrange the output in two columns, one for the descriptive text and the other for the attribute values. Hint: Use addition AT
of the WRITE statement to place the output in a given column. To facilitate later adjustments, do not use a literal for the number. Define private constant C_POS_1 instead. 10. Save, check, and activate your code before running the program.
48
© Copyright. All rights reserved.
Unit 2 Solution 2 Create Local Classes
Business Example You are a developer for an airline corporation that owns several airline carriers. You need to develop an object-oriented program that can manage airline carriers and their airlines. For this reason, you must be able to define classes, attributes, and methods. Template None Solution SAPBC401_BAS_S1 Create a Program 1. Create an executable program, ZBC401_##_MAIN, without a TOP include. Note: In the exercises for this course, when the input values include ##, replace ## with your group number. a) To start the Object Navigator, enter transaction code SE80. b) In the unnamed dropdown list on the left of the screen, choose Package, specify the name of the package ZBC401_## and press ENTER. A Create Object dialog box displays. c) To create the package, choose Yes. A Create Package dialog box displays. d) In the Create Package dialog box, enter a short description for the package and choose Continue. e) In the Prompt for transportable Workbench request dialog box, choose Own Requests. f) Choose a request and choose Continue. g) Under Object Name, choose the package name and choose Create → Program from the context menu. h) In the Create Program dialog box, enter ZBC401_##_MAIN in the Program field and choose Continue. i) In the ABAP: Program Attributes ZBC401_##_MAIN Change dialog box, enter a title for the program. Leave all other default settings and choose Save. j) In the Create Object Directory Entry dialog box, assign the program to your own package, ZBC401_## and choose Save.
© Copyright. All rights reserved.
49
Unit 2: Fundamental Object-Oriented Syntax
k) In the Prompt for transportable Workbench request dialog box, assign the program to your own transport request and choose Continue. The ABAP Editor: Change Report ZBC401_##_MAIN screen displays. Define and Implement a Local Class Declare and implement a class for airplanes. 1. Within your main program, declare the local class LCL_AIRPLANE. a) See the source code extract from the model solution. 2. Define the following attributes: Table 3: Attributes Attribute Name/description Data type
Attribute Type
MV_NAME (name of airplane)
STRING
Private instance attribute
MV_PLANETYPE (type of airplane)
SAPLANE-PLANETYPE
Private instance attribute
GV_N_O_AIRPLANES (instance counter)
I
Private static attribute
a) See the source code extract from the model solution. 3. Define the public instance method SET_ATTRIBUTES for setting private instance attributes. Your method signature must consist of two suitable import parameters defined as compatible with the two attributes. a) See the source code extract from the model solution 4. Implement the public instance method SET_ATTRIBUTES in such a way that the two instance attributes are set. a) See the source code extract from the model solution. 5. Define the public instance method DISPLAY_ATTRIBUTES for displaying private instance attributes. a) See the source code extract from the model solution. 6. Implement the public instance method DISPLAY_ATTRIBUTES in such a way that the values of the two instance attributes are output as an ABAP list. You can also output icons from the type group ICON. a) See the source code extract from the model solution.
Hint: From SAP NetWeaver 7.02, you no longer need to load type groups explicitly using the TYPE-POOLS statement. 7. Define the public static method DISPLAY_N_O_AIRPLANES to display the private static attribute. a) See the source code extract from the model solution.
50
© Copyright. All rights reserved.
Lesson: Creating Local Classes
8. Implement the public static method DISPLAY_N_O_AIRPLANES in such a way that the value of the static attributes is output in the ABAP list. a) See the source code extract from the model solution.
Note: So far, your class does not have a mechanism for ensuring that the instance counter increases each time an object is created. Decide if you want to omit the counter for now, or if you want to temporarily control increments using the SET_ATTRIBUTES method. 9. To improve the list output, arrange the output in two columns, one for the descriptive text and the other for the attribute values. Hint: Use addition AT of the WRITE statement to place the output in a given column. To facilitate later adjustments, do not use a literal for the number. Define private constant C_POS_1 instead. a) See the source code extract from the model solution. 10. Save, check, and activate your code before running the program. a) Save your program. b) To check your program, on the application toolbar choose the Check button. c) To activate your program, on the application toolbar choose the Activate button. d) To run your program, on the application toolbar choose the Direct Processing button. Solution: SAPBC401_BAS_S1 REPORT sapbc401_bas_s1. TYPE-POOLS icon. *--------------------------------------------------------* * CLASS lcl_airplane DEFINITION * *--------------------------------------------------------* CLASS lcl_airplane DEFINITION. PUBLIC SECTION. METHODS: set_attributes IMPORTING iv_name TYPE string iv_planetype TYPE saplane-planetype, display_attributes. CLASS-METHODS: display_n_o_airplanes. PRIVATE SECTION. CONSTANTS: c_pos_1 TYPE i VALUE 30.
© Copyright. All rights reserved.
51
Unit 2: Fundamental Object-Oriented Syntax
DATA: mv_name TYPE string, mv_planetype TYPE saplane-planetype. CLASS-DATA: gv_n_o_airplanes TYPE i. ENDCLASS. "lcl_airplane DEFINITION *--------------------------------------------------------* * CLASS lcl_airplane IMPLEMENTATION * *--------------------------------------------------------* CLASS lcl_airplane IMPLEMENTATION. METHOD set_attributes. mv_name = iv_name. mv_planetype = iv_planetype. * doesn't make sense so much, only in order to get an effect * after calling display_n_o_airplanes: gv_n_o_airplanes = gv_n_o_airplanes + 1. ENDMETHOD. "set_attributes METHOD display_attributes. WRITE: / icon_ws_plane AS ICON, / 'Name of Airplane'(001) , AT c_pos_1 mv_name, / 'Type of Airplane:'(002), AT c_pos_1 mv_planetype. ENDMETHOD. "display_attributes METHOD display_n_o_airplanes. SKIP. WRITE: / 'Number of airplanes:'(ca1), AT c_pos_1 gv_n_o_airplanes LEFT-JUSTIFIED. ENDMETHOD. "display_n_o_airplanes ENDCLASS. "lcl_airplane IMPLEMENTATION
52
© Copyright. All rights reserved.
Lesson: Creating Local Classes
LESSON SUMMARY You should now be able to: ●
Define local classes
●
Define attributes
●
Create methods
© Copyright. All rights reserved.
53
Unit 2 Lesson 2 Creating Objects
LESSON OVERVIEW This lesson explains the concept of creating objects. Business Example As a developer, you want to create multiple instances for the local class that you have created in your ABAP Objects project. For this reason, you require an understanding of how to create objects. LESSON OBJECTIVES After completing this lesson, you will be able to: ●
Create objects
Objects as Instances of Classes
Figure 44: Overview of Instances of Classes
A class contains the generic description of an object and describes the characteristics that all objects in that class have in common. During the program runtime, you use the class to create discrete objects (instances) in the memory. This process is called instantiation. When the class is accessed for the first time, it is loaded into memory. Hint: Although you can use classes and static components to write complete applications, the reason for using object-oriented programming is to create and work with run time instances of classes.
54
© Copyright. All rights reserved.
Lesson: Creating Objects
Definition of Reference Variables
Figure 45: Definition of Reference Variables
The statement DATA go_vehicle1 TYPE REF TO lcl_vehicle defines a reference variable. This variable can point to instances of the class lcl_vehicle. The initial value of a reference variable is an empty reference, that is, the reference points to nothing at all. Creating Objects
Figure 46: Creating Objects
The CREATE OBJECT statement creates an object in the memory. The object attribute values are initial or assigned according to the TYPE specification.
© Copyright. All rights reserved.
55
Unit 2: Fundamental Object-Oriented Syntax
Reference Semantics of Object References
Figure 47: Reference Semantics of Object References
Object reference variables can be assigned to each other. The figure, Reference Semantics of Object References, illustrates an example in which, after the COMPUTE statement, GO_VEHICLE1 and GO_VEHICLE2 point to the same object.
The Garbage Collector
Figure 48: The Garbage Collector
Independent references are references that have not been defined within a class. The Garbage Collector is a routine that starts automatically whenever the runtime system does not have more important tasks to carry out. In this example, the reference to object (2) LCL_OBJECT is initialized. However, there is no subsequent reference point to this object. Therefore, the Garbage Collector deletes the unreferenced object. Because there is no reference point to object (4) LCL_OBJECT, it is also deleted.
56
© Copyright. All rights reserved.
Lesson: Creating Objects
You can use logical query IF go_obj IS INITIAL to determine whether go_obj contains the null reference or does not point to any object.
Caution: You can have object references and data references. In case of data references do not use IS BOUND. In the case of object references, you can work with IS INITIAL and IS BOUND.
Multiple Instances
Figure 49: Reference Administration with Multiple Instantiation
To keep several objects from the same class in your program, you can define an internal table with one column that contains the object references for this class. To maintain the objects in the table, you can use statements for internal tables, such as APPEND, READ, or LOOP.
© Copyright. All rights reserved.
57
Unit 2: Fundamental Object-Oriented Syntax
Example of Aggregation
Figure 50: Example of Aggregation
The objects in the LCL_WHEEL class have their own identity. You can create objects regardless of the existence of an object in the LCL_VEHICLE class. References are transferred to objects in class LCL_VEHICLE to create the desired association.
58
© Copyright. All rights reserved.
Unit 2 Exercise 3 Create Objects
Business Example As a developer, create instances of your airplane class and ensure that the references to the objects are not lost.
Note: This exercise uses the main program file ZBC401_##_MAIN completed in the previous exercise. If not complete, copy the model solution from the previous exercise. In the exercises for this course, when the input values include ##, replace ## with your group number. Template SAPBC401_BAS_S1 Solution SAPBC401_BAS_S2 Define Variables Define a reference variable. 1. Define a reference variable for the instances of your class LCL_AIRPLANE. 2. Define an internal table for buffering references to instances of the LCL_AIRPLANE class. Create Objects Create airplane objects. 1. Create several instances of local class LCL_AIRPLANE and buffer their references in the internal table. Hint: Use the ABAP keyword START-OF-SELECTION to specify where the executable part of the main program begins. Otherwise, the executable statements are classified as unreachable by the syntax check. 2. Save, check, and activate your program. 3. Observe the execution of the program in the ABAP Debugger.
© Copyright. All rights reserved.
59
Unit 2 Solution 3 Create Objects
Business Example As a developer, create instances of your airplane class and ensure that the references to the objects are not lost.
Note: This exercise uses the main program file ZBC401_##_MAIN completed in the previous exercise. If not complete, copy the model solution from the previous exercise. In the exercises for this course, when the input values include ##, replace ## with your group number. Template SAPBC401_BAS_S1 Solution SAPBC401_BAS_S2 Define Variables Define a reference variable. 1. Define a reference variable for the instances of your class LCL_AIRPLANE. a) See the source code extract from the model solution. 2. Define an internal table for buffering references to instances of the LCL_AIRPLANE class. a) See the source code extract from the model solution. Create Objects Create airplane objects. 1. Create several instances of local class LCL_AIRPLANE and buffer their references in the internal table. Hint: Use the ABAP keyword START-OF-SELECTION to specify where the executable part of the main program begins. Otherwise, the executable statements are classified as unreachable by the syntax check. a) See the source code extract from the model solution. 2. Save, check, and activate your program. a) Save your program.
60
© Copyright. All rights reserved.
Lesson: Creating Objects
b) To check your program, on the application toolbar choose the Check button. c) To activate your program, on the application toolbar choose the Activate button. 3. Observe the execution of the program in the ABAP Debugger. a) To start the ABAP Debugger, choose Program → Execute → Debugging. b) To debug your program, on the application toolbar choose the Execute button, or press F8. Solution: SAPBC401_BAS_S2 REPORT sapbc401_bas_s2. TYPE-POOLS icon. *--------------------------------------------------------* * CLASS lcl_airplane DEFINITION *--------------------------------------------------------* CLASS lcl_airplane DEFINITION. * ... ENDCLASS. "lcl_airplane DEFINITION *--------------------------------------------------------* * CLASS lcl_airplane IMPLEMENTATION *--------------------------------------------------------* CLASS lcl_airplane IMPLEMENTATION. * ... ENDCLASS. "lcl_airplane IMPLEMENTATION DATA: DATA:
go_airplane TYPE REF TO lcl_airplane. gt_airplanes TYPE TABLE OF REF TO lcl_airplane.
START-OF-SELECTION. CREATE OBJECT go_airplane. APPEND go_airplane TO gt_airplanes. CREATE OBJECT go_airplane. APPEND go_airplane TO gt_airplanes. CREATE OBJECT go_airplane. APPEND go_airplane TO gt_airplanes.
© Copyright. All rights reserved.
61
Unit 2: Fundamental Object-Oriented Syntax
LESSON SUMMARY You should now be able to: ●
62
Create objects
© Copyright. All rights reserved.
Unit 2 Lesson 3 Accessing Methods and Attributes
LESSON OVERVIEW This lesson explains the process of accessing methods and attributes. Business Example As a developer, you need to explain the various ways of accessing methods and attributes of a class. For this reason, you require the following knowledge: ●
An understanding of calling methods
●
An understanding of accessing attributes
LESSON OBJECTIVES After completing this lesson, you will be able to: ●
Call instance methods
●
Call static methods
●
Call functional methods
●
Access public attributes
Instance Method Calls
Figure 51: Calling Methods
This section explains the use of classes and their instances, from the static connections of various instances to their practical effects.
© Copyright. All rights reserved.
63
Unit 2: Fundamental Object-Oriented Syntax
The example in the figure, Calling Methods, shows the shorter syntax for method calls in which the CALL-METHOD prefix is omitted. Syntax for Calling Instance Methods
Figure 52: Calling Instance Methods – Syntax
CALL METHOD ref->method_name is the syntax used to call instance methods. When calling an instance method from within another instance method, you can omit the instance name ref. The method is automatically executed for the current object. A shorter syntax is also supported as of SAP Web AS 6.10. In this version, omit CALL METHOD and list the parameters in parentheses. There must be no space before the parentheses, but there must be at least one space after the parentheses. When you call a method that has only one import parameter, you can specify the actual parameter in the parentheses without any other additions. When you call a method that only has import parameters, you can omit the EXPORTING addition.
64
© Copyright. All rights reserved.
Lesson: Accessing Methods and Attributes
Static Method Calls
Figure 53: Calling Static Methods – Syntax
Using addition RECEIVING excludes the usage of additions IMPORTING and CHANGING. Apart from that, the same rules apply here as they do for calling a function module. Use CALLMETHOD classname=>method_name to call static methods (also referred to as class methods). Like static attributes, static methods are addressed with their class name, since they do not need instances. As with instance methods, when you call a static method from the class, you can omit the class name; otherwise, the same rules apply here as for calling an instance method.
© Copyright. All rights reserved.
65
Unit 2: Fundamental Object-Oriented Syntax
Functional Method Calls
Figure 54: Functional Methods
Methods that have a RETURNING parameter are described as functional methods. The RETURNING parameter must always be passed by value - RETURNING VALUE(...) - and not by reference.
Note: Prior to SAP NetWeaver 7.40 functional methods were only allowed IMPORTING parameters and exceptions, in addition to their RETURNING parameter. From SAP NetWeaver 7.40 onwards, they may have any number of EXPORTING and CHANGING parameters. You can directly call functional methods within the following expressions: ●
Logical expressions: IF, ELSEIF, WHILE, CHECK, WAIT
●
Arithmetic expressions and bit expressions: COMPUTE
●
Case conditions: CASE, WHEN
Note: In SAP NetWeaver 7.02 the list of positions at which functional methods can be used was extended considerably.
66
© Copyright. All rights reserved.
Lesson: Accessing Methods and Attributes
Functional Methods – Examples
Figure 55: Functional Methods – Examples
In the first part of the example, the two functional instance method calls represent the two addends of an addition. The second example shows the call of a functional static method in short form. The GV_NUMBER data object is the actual parameter for the RETURNING parameter of the method. The detailed syntax is as follows: DATA gv_number TYPE i. ... CALL METHOD lcl_vehicle=>get_n_o_vehicles RECEIVING rv_count = gv_number.
Access to Public Attributes
Figure 56: Accessing Public Attributes
© Copyright. All rights reserved.
67
Unit 2: Fundamental Object-Oriented Syntax
You can access public attributes from outside the class in the same way as method calls. You can access static attributes using CLASSNAME=>STATIC_ATTRIBUTE. Access instance attributes with REF->INSTANCE_ATTRIBUTE.
68
© Copyright. All rights reserved.
Unit 2 Exercise 4 Call Methods
Business Example As a developer, you need to fill the attributes of the objects with suitable values. You need to know how to define and call methods.
Note: This exercise uses the main program file ZBC401_##_MAIN completed in the previous exercise. If not complete, copy the model solution from the previous exercise. In the exercises for this course, when the input values include ##, replace ## with your group number. Template SAPBC401_BAS_S2 Solution SAPBC401_BAS_S3 Calling Methods Call the methods of your class. 1. Call the static method DISPLAY_N_O_AIRPLANES twice: Once before and once after the instantiations. 2. Use the SET_ATTRIBUTES method to set the attributes for all objects. Choose a unique name for each airplane type (for example, 747-400). When assigning airplane types, use the information in the SAPLANE table as a guide. 3. Display the attribute values for all airplanes in a loop in the ABAP list, using the DISPLAY_ATTRIBUTES method. Adding Functional Methods Add a functional method to your class. 1. Define the public static functional method GET_N_O_AIRPLANES in the class. The Method signature must only consist of result parameter RV_COUNT, which must be an integer. 2. Call this method in the main program and output the value in the ABAP list. 3. Save, check, and activate your code before running the program.
© Copyright. All rights reserved.
69
Unit 2 Solution 4 Call Methods
Business Example As a developer, you need to fill the attributes of the objects with suitable values. You need to know how to define and call methods.
Note: This exercise uses the main program file ZBC401_##_MAIN completed in the previous exercise. If not complete, copy the model solution from the previous exercise. In the exercises for this course, when the input values include ##, replace ## with your group number. Template SAPBC401_BAS_S2 Solution SAPBC401_BAS_S3 Calling Methods Call the methods of your class. 1. Call the static method DISPLAY_N_O_AIRPLANES twice: Once before and once after the instantiations. a) See the source code extract from the model solution. Note: For reasons explained in the exercise Create UML Diagrams, you may not notice any effects at the moment. 2. Use the SET_ATTRIBUTES method to set the attributes for all objects. Choose a unique name for each airplane type (for example, 747-400). When assigning airplane types, use the information in the SAPLANE table as a guide. a) See the source code extract from the model solution. 3. Display the attribute values for all airplanes in a loop in the ABAP list, using the DISPLAY_ATTRIBUTES method. a) See the source code extract from the model solution. Adding Functional Methods Add a functional method to your class. 1. Define the public static functional method GET_N_O_AIRPLANES in the class. The Method signature must only consist of result parameter RV_COUNT, which must be an integer.
70
© Copyright. All rights reserved.
Lesson: Accessing Methods and Attributes
a) See the source code extract from the model solution. 2. Call this method in the main program and output the value in the ABAP list. a) See the source code extract from the model solution. 3. Save, check, and activate your code before running the program. a) Save your program. b) To check your program, on the application toolbar choose the Check button. c) To activate your program, on the application toolbar choose the Activate button. d) To run your program, on the application toolbar choose the Direct Processing button. Solution: SAPBC401_BAS_S3 Report SAPBC401_BAS_S3. TYPE-POOLS icon. *----------------------------------------------* * CLASS lcl_airplane DEFINITION *----------------------------------------------* CLASS lcl_airplane DEFINITION. PUBLIC SECTION. METHODS: set_attributes IMPORTING iv_name TYPE string iv_planetype TYPE saplane-planetype, display_attributes. CLASS-METHODS: display_n_o_airplanes, get_n_o_airplanes RETURNING value(rv_count) TYPE i.
PRIVATE SECTION. CONSTANTS:
c_pos_1 TYPE i VALUE 30.
DATA: mv_name TYPE string, mv_planetype TYPE saplane-planetype. CLASS-DATA: gv_n_o_airplanes TYPE i. ENDCLASS. "lcl_airplane DEFINITION *----------------------------------------------* * CLASS lcl_airplane IMPLEMENTATION *----------------------------------------------* CLASS lcl_airplane IMPLEMENTATION. METHOD
set_attributes.
mv_planetype = iv_planetype. * doesn't make sense so much, * only in order to get an effect * after calling display_n_o_airplanes:
© Copyright. All rights reserved.
71
Unit 2: Fundamental Object-Oriented Syntax
gv_n_o_airplanes = gv_n_o_airplanes + 1. ENDMETHOD. "set_attributes METHOD
display_attributes.
WRITE: / icon_ws_plane AS ICON, / 'Name of Airplane'(001) , AT c_pos_1 mv_name, / 'Type of Airplane:'(002), AT c_pos_1 mv_planetype. ENDMETHOD. "display_attributes METHOD display_n_o_airplanes. SKIP. WRITE: / 'Number of airplanes:'(ca1), AT c_pos_1 gv_n_o_airplanes LEFT-JUSTIFIED. ENDMETHOD. "display_n_o_airplanes METHOD get_n_o_airplanes. rv_count = gv_n_o_airplanes. ENDMETHOD. "get_n_o_airplanes ENDCLASS. "lcl_airplane IMPLEMENTATION DATA: go_airplane TYPE REF TO lcl_airplane, gt_airplanes TYPE TABLE OF REF TO lcl_airplane, gv_count TYPE i. START-OF-SELECTION. lcl_airplane=>display_n_o_airplanes( ). CREATE OBJECT go_airplane. APPEND go_airplane TO gt_airplanes. go_airplane->set_attributes( iv_name = 'LH Berlin' iv_planetype = 'A321' ). CREATE OBJECT go_airplane. APPEND go_airplane TO gt_airplanes. go_airplane->set_attributes( iv_name = 'AA New York' iv_planetype = '747-400' ). CREATE OBJECT go_airplane. APPEND go_airplane TO gt_airplanes. go_airplane->set_attributes( iv_name = 'US Hercules' iv_planetype = '747-200F' ). LOOP AT gt_airplanes INTO go_airplane. go_airplane->display_attributes( ). ENDLOOP. * long syntax for functional call: * CALL METHOD lcl_airplane=>get_n_o_airplanes * RECEIVING
72
© Copyright. All rights reserved.
Lesson: Accessing Methods and Attributes
* * * * * * *
rv_count = gv_count. a little bit shorter: lcl_airplane=>get_n_o_airplanes( RECEIVING rv_count = gv_count ). the shortest syntax for functional call:
gv_count = lcl_airplane=>get_n_o_airplanes( ). SKIP 2. WRITE: / 'Number of airplanes'(ca1), gv_count.
© Copyright. All rights reserved.
73
Unit 2: Fundamental Object-Oriented Syntax
LESSON SUMMARY You should now be able to:
74
●
Call instance methods
●
Call static methods
●
Call functional methods
●
Access public attributes
© Copyright. All rights reserved.
Unit 2 Lesson 4 Implementing Constructors in Local Classes
LESSON OVERVIEW This lesson explains the implementation of constructor methods in local classes. Business Example As a developer, you must explain the creation and use of instance constructors for the class in your ABAP Objects project. For this reason, you require the following knowledge: ●
An understanding of instance constructors
●
An understanding of how to use instance constructors
LESSON OBJECTIVES After completing this lesson, you will be able to: ●
Create and use constructors
Instance Constructor
Figure 57: Instance Constructor
There are two types of methods in ABAP Objects. ABAP Objects can be called implicitly or explicitly with the CALL METHOD syntax. Constructors are the first type of method.
© Copyright. All rights reserved.
75
Unit 2: Fundamental Object-Oriented Syntax
The instance constructor is a special instance method in a class and is always named CONSTRUCTOR. The constructor is automatically called at runtime with the CREATE OBJECT statement. When defining constructors, always consider the following points: ●
No class can have more than one instance constructor.
●
A constructor must be defined in the public area.
●
The constructor signature can only include importing parameters and exceptions.
●
●
When exceptions are raised in the constructor, no instances are created and no main memory space is occupied. Except for one unique case, you cannot call the constructor explicitly.
Note: There is no destructor in ABAP Objects; that is, there is no instance method that is automatically called from the memory immediately before the object is deleted. The corresponding comments in the SAP Library and the menu paths outside the ABAP Workbench are only contained in internal system calls. Constructor – Example
Figure 58: Constructor – Example
After the instantiation of a class, a constructor is necessary when some of the following conditions occur: ●
●
76
You must allocate resources. You must initialize attributes that cannot be covered by the VALUE addition to the DATA statement.
© Copyright. All rights reserved.
Lesson: Implementing Constructors in Local Classes
●
You modify static attributes.
●
You must inform other objects about the object creation.
© Copyright. All rights reserved.
77
Unit 2: Fundamental Object-Oriented Syntax
78
© Copyright. All rights reserved.
Unit 2 Exercise 5 Create and Use Constructors
Business Example Define and implement instance constructors. Create instances of classes that contain an instance constructor. Define, raise and handle classical, non-class-based exceptions.
Note: This exercise uses the main program file ZBC401_##_MAIN completed in the previous exercise. If not complete, copy the model solution from the previous exercise. In the exercises for this course, when the input values include ##, replace ## with your group number. Template SAPBC401_BAS_S3 Solution SAPBC401_BAS_S4 Define an Instance Constructor Define an instance constructor. 1. Define a constructor with a suitable signature for the instances of your class LCL_AIRPLANE. 2. Implement the constructor in a way that the two instance attributes are set and instance counter GV_N_O_AIRPLANES is increased by one. 3. Remove the definition and implementation of method SET_ATTRIBUTES to ensure that an attribute of instance can be set only once during its creation. Create New Objects Create airplane objects. 1. Your CREATE OBJECT statements from the previous exercise are now syntactically incorrect. Adapt and correct them. 2. Remove calls of the SET_ATTRIBUTES method. 3. Save, check, and activate your program. 4. Follow the execution of the program in the ABAP Debugger. Set Instance Attributes to Access a Database Table Define additional instance attributes with technical information about the airplane. Set these attributes in your constructor by accessing database table SAPLANE. Raise an exception if the specified plane type is not found in the database.
© Copyright. All rights reserved.
79
Unit 2: Fundamental Object-Oriented Syntax
1. In the class LCL_AIRPLANE, define private instance attributes MV_WEIGHT (data type SAPLANE-WEIGHT) and MV_TANKCAP (data type SAPLANE-TANKCAP). 2. In the method DISPLAY_ATTRIBUTES, use WRITE statements to output the additional attributes. 3. Extend the definition of the instance constructor by adding a classical exception that is not class-based, WRONG_PLANETYPE. 4. Extend the implementation of the constructor. Read a single record from database table SAPLANE for the specified plane type and set new attributes accordingly. Raise the exception when no data is found for the given plane type. 5. Adjust the CREATE OBJECT statements so that you handle the exception. Only store the object reference in your table when the creation is successful. 6. Save, check, and activate your program. 7. Follow the execution of the program in the ABAP Debugger. For test purposes, specify a non-existing airplane type to see how the exception handling works.
80
© Copyright. All rights reserved.
Unit 2 Solution 5 Create and Use Constructors
Business Example Define and implement instance constructors. Create instances of classes that contain an instance constructor. Define, raise and handle classical, non-class-based exceptions.
Note: This exercise uses the main program file ZBC401_##_MAIN completed in the previous exercise. If not complete, copy the model solution from the previous exercise. In the exercises for this course, when the input values include ##, replace ## with your group number. Template SAPBC401_BAS_S3 Solution SAPBC401_BAS_S4 Define an Instance Constructor Define an instance constructor. 1. Define a constructor with a suitable signature for the instances of your class LCL_AIRPLANE. a) See the source code extract from the model solution. 2. Implement the constructor in a way that the two instance attributes are set and instance counter GV_N_O_AIRPLANES is increased by one. a) See the source code extract from the model solution. 3. Remove the definition and implementation of method SET_ATTRIBUTES to ensure that an attribute of instance can be set only once during its creation. a) See the source code extract from the model solution. Create New Objects Create airplane objects. 1. Your CREATE OBJECT statements from the previous exercise are now syntactically incorrect. Adapt and correct them. a) See the source code extract from the model solution. 2. Remove calls of the SET_ATTRIBUTES method. a) See the source code extract from the model solution. 3. Save, check, and activate your program.
© Copyright. All rights reserved.
81
Unit 2: Fundamental Object-Oriented Syntax
a) Save your program. b) To check your program, on the application toolbar choose the Check button. c) To activate your program, on the application toolbar choose the Activate button. 4. Follow the execution of the program in the ABAP Debugger. a) To start the ABAP Debugger, choose Program → Execute → Debugging. b) To debug your program, on the application toolbar choose the Execute button, or press F8. Set Instance Attributes to Access a Database Table Define additional instance attributes with technical information about the airplane. Set these attributes in your constructor by accessing database table SAPLANE. Raise an exception if the specified plane type is not found in the database. 1. In the class LCL_AIRPLANE, define private instance attributes MV_WEIGHT (data type SAPLANE-WEIGHT) and MV_TANKCAP (data type SAPLANE-TANKCAP). a) See the source code extract from the model solution. 2. In the method DISPLAY_ATTRIBUTES, use WRITE statements to output the additional attributes. a) See the source code extract from the model solution. 3. Extend the definition of the instance constructor by adding a classical exception that is not class-based, WRONG_PLANETYPE. a) See the source code extract from the model solution. 4. Extend the implementation of the constructor. Read a single record from database table SAPLANE for the specified plane type and set new attributes accordingly. Raise the exception when no data is found for the given plane type. a) See the source code extract from the model solution. 5. Adjust the CREATE OBJECT statements so that you handle the exception. Only store the object reference in your table when the creation is successful. a) See the source code extract from the model solution. 6. Save, check, and activate your program. 7. Follow the execution of the program in the ABAP Debugger. For test purposes, specify a non-existing airplane type to see how the exception handling works. a) To start the ABAP Debugger, choose Program → Execute → Debugging. b) To debug your program, on the application toolbar choose the Execute button, or press F8. Solution: SAPBC401_BAS_S4 REPORT
sapbc401_bas_s4.
TYPE-POOLS icon. *-------------------------------------------------* * CLASS lcl_airplane DEFINITION * *-------------------------------------------------*
82
© Copyright. All rights reserved.
Lesson: Implementing Constructors in Local Classes
CLASS lcl_airplane DEFINITION. PUBLIC SECTION. METHODS: constructor IMPORTING iv_name TYPE string iv_planetype TYPE saplane-planetype EXCEPTIONS wrong_planetype, display_attributes. CLASS-METHODS: display_n_o_airplanes, get_n_o_airplanes RETURNING value(rv_count) TYPE i. PRIVATE SECTION. CONSTANTS: c_pos_1 TYPE i VALUE 30. DATA: mv_name mv_planetype mv_weight mv_tankcap
TYPE TYPE TYPE TYPE
string, saplane-planetype, saplane-weight, saplane-tankcap.
CLASS-DATA: gv_n_o_airplanes TYPE i. ENDCLASS.
"lcl_airplane DEFINITION
*--------------------------------------------------* * CLASS lcl_airplane IMPLEMENTATION * *--------------------------------------------------* CLASS lcl_airplane IMPLEMENTATION. METHOD constructor. DATA: ls_planetype TYPE saplane. mv_name = iv_name. mv_planetype = iv_planetype. SELECT SINGLE * FROM saplane INTO ls_planetype WHERE planetype = iv_planetype. IF sy-subrc <> 0. RAISE wrong_planetype. ELSE. mv_weight = ls_planetype-weight. mv_tankcap = ls_planetype-tankcap. gv_n_o_airplanes = gv_n_o_airplanes + 1. ENDIF. ENDMETHOD.
"constructor
METHOD display_attributes.
© Copyright. All rights reserved.
83
Unit 2: Fundamental Object-Oriented Syntax
WRITE: / icon_ws_plane AS ICON, / 'Name of Airplane'(001) , / 'Type of Airplane:'(002), / 'Weight:'(003), LEFT-JUSTIFIED, / 'Tank capacity:'(004), LEFT-JUSTIFIED. ENDMETHOD.
AT c_pos_1 mv_name, AT c_pos_1 mv_planetype, AT c_pos_1 mv_weight AT c_pos_1 mv_tankcap
"display_attributes
METHOD display_n_o_airplanes. SKIP. WRITE: / 'Number of airplanes:'(ca1), AT c_pos_1 gv_n_o_airplanes LEFT-JUSTIFIED. ENDMETHOD. "display_n_o_airplanes METHOD get_n_o_airplanes. rv_count = gv_n_o_airplanes. ENDMETHOD. "get_n_o_airplanes ENDCLASS.
"lcl_airplane IMPLEMENTATION
DATA: go_airplane TYPE REF TO lcl_airplane, gt_airplanes TYPE TABLE OF REF TO lcl_airplane, gv_count TYPE i. START-OF-SELECTION. ******************* lcl_airplane=>display_n_o_airplanes( ). CREATE OBJECT go_airplane EXPORTING iv_name = 'LH Berlin' iv_planetype = 'A321' EXCEPTIONS wrong_planetype = 1. IF sy-subrc = 0. APPEND go_airplane TO gt_airplanes. ENDIF. CREATE OBJECT go_airplane EXPORTING iv_name = 'AA New York' iv_planetype = '747-400' EXCEPTIONS wrong_planetype = 1. IF sy-subrc = 0. APPEND go_airplane TO gt_airplanes. ENDIF. CREATE OBJECT go_airplane EXPORTING iv_name = 'US Hercules' iv_planetype = '747-200F' EXCEPTIONS wrong_planetype = 1.
84
© Copyright. All rights reserved.
Lesson: Implementing Constructors in Local Classes
IF sy-subrc = 0. APPEND go_airplane TO gt_airplanes. ENDIF. LOOP AT gt_airplanes INTO go_airplane. go_airplane->display_attributes( ). ENDLOOP. gv_count = lcl_airplane=>get_n_o_airplanes( ). SKIP 2. WRITE: / 'Number of airplanes'(ca1), gv_count.
© Copyright. All rights reserved.
85
Unit 2: Fundamental Object-Oriented Syntax
LESSON SUMMARY You should now be able to: ●
86
Create and use constructors
© Copyright. All rights reserved.
Unit 2 Lesson 5 Implementing Class Constructors in Local Classes
LESSON OVERVIEW This lesson explains the creation and use of static constructors and self-references. Business Example As a developer, you need to explain the creation and use of static constructors for the classes in your ABAP Objects project. ●
An understanding of static constructors
●
An understanding of self-reference
LESSON OBJECTIVES After completing this lesson, you will be able to: ●
Create and use static constructors
Static Constructor
Figure 59: Example of a Static Constructor
The static constructor is a special static method and is always named CLASS_CONSTRUCTOR. The static constructor is executed only once per program. The static constructor is called by the system automatically before the class is first accessed and before the first execution of the following actions:
© Copyright. All rights reserved.
87
Unit 2: Fundamental Object-Oriented Syntax
●
When an instance of the class (CREATE OBJECT) is created.
●
When a static attribute of the class is accessed.
●
When a static method of the class is called.
●
When an event handler method for an event in the class is being registered.
When you define static constructors, always consider the following points: ●
Each class does not have more than one static constructor.
●
The static constructor must be defined in the public area.
●
The static constructor does not have any parameters or exceptions.
●
The static constructor cannot be called explicitly.
Self-Reference
Figure 60: Self-Reference
In some cases, you must also have a self-reference available. In ABAP Objects, self-references are always predefined, but they are only useful and syntactically available in certain contexts. You can address an object itself by using the predefined reference variable ME within its instance methods. You are not required to use me-> as a prefix in such cases, but you can use it to improve readability. However, you must use the prefix me-> when distinguishing between local data objects and instance attributes with the same name. An important use of self reference is when you call a foreign method and a client object is required to export a reference to itself, you can then use ME as an actual parameter with EXPORTING or CHANGING.
88
© Copyright. All rights reserved.
Unit 2 Exercise 6 Create and Use Static Constructors
Business Example For performance reasons, you do not want to access the database each time an instance is created. Therefore, read all the data just once in the static constructor and store it in a static attribute.
Note: This exercise uses the main program file ZBC401_##_MAIN completed in the previous exercise. If not complete, copy the model solution from the previous exercise. In the exercises for this course, when the input values include ##, replace ## with your group number. Template SAPBC401_BAS_S4 Solution SAPBC401_BAS_S5 Use the Static Constructor to Buffer Data Use a static attribute to buffer data from database table SAPLANE. Fill it using the static constructor. 1. Define internal table GT_PLANETYPES as a private static attribute. To specify the type for the GT_PLANETYPES internal table, define private table type TY_PLANETYPES in the class definition. Use the PLANETYPE field as a key for the internal table. 2. Define a static constructor in the LCL_AIRPLANE class. 3. Implement the constructor in such a way that the GT_PLANETYPES internal table is filled with all rows from the SAPLANE database table. You can use the ARRAY FETCH technique for this purpose. 4. Save, check, and activate your program. 5. Use the ABAP Debugger to ensure that the static constructor is called correctly and that the internal table is filled in the main program. 6. Where is the static constructor called in the main program?
© Copyright. All rights reserved.
89
Unit 2: Fundamental Object-Oriented Syntax
Declare and Implement a Private Static Method Declare and implement a private static method to derive the weight and tank capacity of one plane type from the GT_PLANETYPES table. 1. Within the LCL_AIRPLANE class, define private static method GET_TECHNICAL_ATTRIBUTES. The signature must consist of one import parameter for the airplane type and two export parameters for weight and tank capacity. Use transparent table SAPLANE as a guide for specifying the types of these formal parameters. The signature must contain a classical exception which is raised when no data is found for the specified airplane type. Use a non-class exception. 2. Implement the method in such a way that the values for export parameters are determined by a single-record access to internal table GT_PLANETYPES. When the table does not contain any values for the airplane type, the method raises an exception. Note: The correct unit of measure must also be selected and exported. However, because of time constraints, you do not need to include it in this exercise. Replace the Database Access in the Instance Constructor Replace the database access in the instance constructor calling of method GET_TECHNICAL_ATTRIBUTES. 1. Is it possible to call the new method from the main program? Why is this?
2. Call method GET_TECHNICAL_ATTRIBUTES from the constructor to obtain additional technical data. Depending on the outcome, set the corresponding private attributes or raise the exception of the constructor. 3. Save, check, and activate your program. 4. Observe the execution of the program in the ABAP Debugger. 5. Which alternative solutions could be used to solve the tasks?
90
© Copyright. All rights reserved.
Unit 2 Solution 6 Create and Use Static Constructors
Business Example For performance reasons, you do not want to access the database each time an instance is created. Therefore, read all the data just once in the static constructor and store it in a static attribute.
Note: This exercise uses the main program file ZBC401_##_MAIN completed in the previous exercise. If not complete, copy the model solution from the previous exercise. In the exercises for this course, when the input values include ##, replace ## with your group number. Template SAPBC401_BAS_S4 Solution SAPBC401_BAS_S5 Use the Static Constructor to Buffer Data Use a static attribute to buffer data from database table SAPLANE. Fill it using the static constructor. 1. Define internal table GT_PLANETYPES as a private static attribute. To specify the type for the GT_PLANETYPES internal table, define private table type TY_PLANETYPES in the class definition. Use the PLANETYPE field as a key for the internal table. a) See the source code extract from the model solution. 2. Define a static constructor in the LCL_AIRPLANE class. a) See the source code extract from the model solution. 3. Implement the constructor in such a way that the GT_PLANETYPES internal table is filled with all rows from the SAPLANE database table. You can use the ARRAY FETCH technique for this purpose. a) See the source code extract from the model solution. 4. Save, check, and activate your program. a) Save your program. b) To check your program, on the application toolbar choose the Check button. c) To activate your program, on the application toolbar choose the Activate button.
© Copyright. All rights reserved.
91
Unit 2: Fundamental Object-Oriented Syntax
5. Use the ABAP Debugger to ensure that the static constructor is called correctly and that the internal table is filled in the main program. a) To start the ABAP Debugger, choose Program → Execute → Debugging. b) To debug the program, on the application toolbar choose Execute, or press F8. 6. Where is the static constructor called in the main program? When the class is accessed for the first time which is when the DISPLAY_N_O_AIRPLANES method is called. It runs before the DISPLAY_N_O_AIRPLANES method is executed. Declare and Implement a Private Static Method Declare and implement a private static method to derive the weight and tank capacity of one plane type from the GT_PLANETYPES table. 1. Within the LCL_AIRPLANE class, define private static method GET_TECHNICAL_ATTRIBUTES. The signature must consist of one import parameter for the airplane type and two export parameters for weight and tank capacity. Use transparent table SAPLANE as a guide for specifying the types of these formal parameters. The signature must contain a classical exception which is raised when no data is found for the specified airplane type. Use a non-class exception. a) See the source code extract from the model solution. 2. Implement the method in such a way that the values for export parameters are determined by a single-record access to internal table GT_PLANETYPES. When the table does not contain any values for the airplane type, the method raises an exception. a) See the source code extract from the model solution.
Note: The correct unit of measure must also be selected and exported. However, because of time constraints, you do not need to include it in this exercise. Replace the Database Access in the Instance Constructor Replace the database access in the instance constructor calling of method GET_TECHNICAL_ATTRIBUTES. 1. Is it possible to call the new method from the main program? Why is this? You can only call the new method from the main program if the method is public. Because the new method in this case is a private method, it can only be called from within the LCL_AIRPLANE class. 2. Call method GET_TECHNICAL_ATTRIBUTES from the constructor to obtain additional technical data. Depending on the outcome, set the corresponding private attributes or raise the exception of the constructor. a) See the source code extract from the model solution. 3. Save, check, and activate your program.
92
© Copyright. All rights reserved.
Lesson: Implementing Class Constructors in Local Classes
4. Observe the execution of the program in the ABAP Debugger. 5. Which alternative solutions could be used to solve the tasks? a) Define GET_TECHNICAL_ATTRIBUTES as instance method without the PLANETYPE import parameter. If the method is defined as an instance method, it can access the MV_PLANETYPE attribute directly (as ME->MV_PLANETYPES). In this case, the import parameter is not needed. b) Do not use a method to read GT_PLANETYPES. In the instance constructor, you can access the class attribute GT_PLANETYPES directly (using ME->GT_PLANETYPES). Solution: SAPBC401_BAS_S5 REPORT
sapbc401_bas_s5.
TYPE-POOLS icon. *-------------------------------------------------* * CLASS lcl_airplane DEFINITION *-------------------------------------------------* CLASS lcl_airplane DEFINITION. PUBLIC SECTION. METHODS: constructor IMPORTING iv_name TYPE string iv_planetype TYPE saplane-planetype EXCEPTIONS wrong_planetype, display_attributes. CLASS-METHODS: class_constructor, display_n_o_airplanes, get_n_o_airplanes RETURNING value(rv_count) TYPE i. PRIVATE SECTION. TYPES: ty_planetypes TYPE STANDARD TABLE OF saplane WITH NON-UNIQUE KEY planetype. CONSTANTS: c_pos_1 TYPE i VALUE 30. DATA: mv_name mv_planetype mv_weight mv_tankcap
TYPE TYPE TYPE TYPE
string, saplane-planetype, saplane-weight, saplane-tankcap.
CLASS-DATA: gv_n_o_airplanes TYPE i, gt_planetypes TYPE ty_planetypes.
© Copyright. All rights reserved.
93
Unit 2: Fundamental Object-Oriented Syntax
CLASS-METHODS: get_technical_attributes IMPORTING iv_type TYPE saplane-planetype EXPORTING ev_weight TYPE saplane-weight ev_tankcap TYPE saplane-tankcap EXCEPTIONS wrong_planetype. ENDCLASS.
"lcl_airplane DEFINITION
*------------------------------------------------* * CLASS lcl_airplane IMPLEMENTATION *------------------------------------------------* CLASS lcl_airplane IMPLEMENTATION. METHOD class_constructor. SELECT * FROM saplane INTO TABLE gt_planetypes. ENDMETHOD. "class_constructor *
METHOD constructor. DATA: ls_planetype TYPE saplane. mv_name = iv_name. mv_planetype = iv_planetype.
* * *
* *
SELECT SINGLE * FROM saplane INTO ls_planetype WHERE planetype = iv_planetype. get_technical_attributes( EXPORTING iv_type = iv_planetype IMPORTING ev_weight = mv_weight ev_tankcap = mv_tankcap EXCEPTIONS wrong_planetype = 1 ). IF sy-subrc <> 0. RAISE wrong_planetype. ELSE. mv_weight = ls_planetype-weight. mv_tankcap = ls_planetype-tankcap. gv_n_o_airplanes = gv_n_o_airplanes + 1. ENDIF. ENDMETHOD.
"constructor
METHOD display_attributes. WRITE: / icon_ws_plane AS ICON, / 'Name of Airplane'(001) , / 'Type of Airplane:'(002), / 'Weight:'(003), LEFT-JUSTIFIED, / 'Tank capacity:'(004), LEFT-JUSTIFIED. ENDMETHOD.
94
AT c_pos_1 mv_name, AT c_pos_1 mv_planetype, AT c_pos_1 mv_weight AT c_pos_1 mv_tankcap
"display_attributes
© Copyright. All rights reserved.
Lesson: Implementing Class Constructors in Local Classes
METHOD display_n_o_airplanes. SKIP. WRITE: / 'Number of airplanes:'(ca1), AT c_pos_1 gv_n_o_airplanes LEFT-JUSTIFIED. ENDMETHOD. "display_n_o_airplanes METHOD get_n_o_airplanes. rv_count = gv_n_o_airplanes. ENDMETHOD. "get_n_o_airplanes METHOD get_technical_attributes. DATA: ls_planetype TYPE saplane. READ TABLE gt_planetypes INTO ls_planetype WITH TABLE KEY planetype = iv_type TRANSPORTING weight tankcap. IF sy-subrc = 0. ev_weight = ls_planetype-weight. ev_tankcap = ls_planetype-tankcap. ELSE. RAISE wrong_planetype. ENDIF. ENDMETHOD. "get_technical_attributes ENDCLASS. "lcl_airplane IMPLEMENTATION DATA: go_airplane TYPE REF TO lcl_airplane, gt_airplanes TYPE TABLE OF REF TO lcl_airplane, gv_count TYPE i. START-OF-SELECTION. ******************* lcl_airplane=>display_n_o_airplanes( ). CREATE OBJECT go_airplane EXPORTING iv_name = 'LH Berlin' iv_planetype = 'A321' EXCEPTIONS wrong_planetype = 1. IF sy-subrc = 0. APPEND go_airplane TO gt_airplanes. ENDIF. CREATE OBJECT go_airplane EXPORTING iv_name = 'AA New York' iv_planetype = '747-400' EXCEPTIONS wrong_planetype = 1. IF sy-subrc = 0. APPEND go_airplane TO gt_airplanes. ENDIF. CREATE OBJECT go_airplane EXPORTING iv_name = 'US Hercules' iv_planetype = '747-200F' EXCEPTIONS
© Copyright. All rights reserved.
95
Unit 2: Fundamental Object-Oriented Syntax
wrong_planetype = 1. IF sy-subrc = 0. APPEND go_airplane TO gt_airplanes. ENDIF. LOOP AT gt_airplanes INTO go_airplane. go_airplane->display_attributes( ). ENDLOOP. gv_count = lcl_airplane=>get_n_o_airplanes( ). SKIP 2. WRITE: / 'Number of airplanes'(ca1), gv_count.
96
© Copyright. All rights reserved.
Lesson: Implementing Class Constructors in Local Classes
LESSON SUMMARY You should now be able to: ●
Create and use static constructors
© Copyright. All rights reserved.
97
Unit 2: Fundamental Object-Oriented Syntax
98
© Copyright. All rights reserved.
Unit 2 Learning Assessment
1. The CLASS statement can be nested, that is, you can define a class within a class. Determine whether this statement is true or false. X
True
X
False
2. Which one of the following syntax elements is used to define static attributes? Choose the correct answer. X
A CLASS-DATA
X
B DATA
X
C LIKE
3. Which of the following options is used to create an object? Choose the correct answer. X
A CREATE OBJECT ref_name
X
B APPEND ref_name
X
C CLASS ref_name
4. You must create and address objects using reference variables. Determine whether this statement is true or false. X
True
X
False
5. During program runtime, you create discrete objects (instances) in memory for an existing class. This process is called instantiation. Determine whether this statement is true or false. X
True
X
False
© Copyright. All rights reserved.
99
Unit 2: Learning Assessment
6. When calling a static method from within the class, you can omit the class name. Determine whether this statement is true or false. X
True
X
False
7. In which of the following expressions can functional methods be called directly? Choose the correct answers. X
A IF
X
B COMPUTE
X
C MOVE
X
D WHILE
8. You can describe methods that have a _________ parameter as functional methods. Choose the correct answer. X
A EXPORTING
X
B CHANGING
X
C RETURNING
9. You have to define RETURNING parameters using the VALUE addition, that is they must be pass by value. Determine whether this statement is true or false. X
True
X
False
10. The _____________ is a special instance method in a class. Choose the correct answer.
100
X
A constructor
X
B function
X
C attributes
© Copyright. All rights reserved.
Unit 2: Learning Assessment
11. The instance constructor is automatically called at runtime with the CREATE OBJECT statement. Determine whether this statement is true or false. X
True
X
False
12. Which of the following points are true about the static constructor? Choose the correct answer. X
A Each class has not more than one static constructor.
X
B The static constructor must be defined in the private area.
X
C The static constructor’s signature can have importing parameters or exceptions.
X
D The static constructor must be called explicitly from the class.
13. The instance constructor’s signature can have importing parameters or exceptions. Determine whether this statement is true or false. X
True
X
False
© Copyright. All rights reserved.
101
Unit 2 Learning Assessment - Answers
1. The CLASS statement can be nested, that is, you can define a class within a class. Determine whether this statement is true or false. X
True
X
False
2. Which one of the following syntax elements is used to define static attributes? Choose the correct answer. X
A CLASS-DATA
X
B DATA
X
C LIKE
3. Which of the following options is used to create an object? Choose the correct answer. X
A CREATE OBJECT ref_name
X
B APPEND ref_name
X
C CLASS ref_name
4. You must create and address objects using reference variables. Determine whether this statement is true or false.
102
X
True
X
False
© Copyright. All rights reserved.
Unit 2: Learning Assessment - Answers
5. During program runtime, you create discrete objects (instances) in memory for an existing class. This process is called instantiation. Determine whether this statement is true or false. X
True
X
False
6. When calling a static method from within the class, you can omit the class name. Determine whether this statement is true or false. X
True
X
False
7. In which of the following expressions can functional methods be called directly? Choose the correct answers. X
A IF
X
B COMPUTE
X
C MOVE
X
D WHILE
8. You can describe methods that have a _________ parameter as functional methods. Choose the correct answer. X
A EXPORTING
X
B CHANGING
X
C RETURNING
9. You have to define RETURNING parameters using the VALUE addition, that is they must be pass by value. Determine whether this statement is true or false. X
True
X
False
© Copyright. All rights reserved.
103
Unit 2: Learning Assessment - Answers
10. The _____________ is a special instance method in a class. Choose the correct answer. X
A constructor
X
B function
X
C attributes
11. The instance constructor is automatically called at runtime with the CREATE OBJECT statement. Determine whether this statement is true or false. X
True
X
False
12. Which of the following points are true about the static constructor? Choose the correct answer. X
A Each class has not more than one static constructor.
X
B The static constructor must be defined in the private area.
X
C The static constructor’s signature can have importing parameters or exceptions.
X
D The static constructor must be called explicitly from the class.
13. The instance constructor’s signature can have importing parameters or exceptions. Determine whether this statement is true or false.
104
X
True
X
False
© Copyright. All rights reserved.
UNIT 3
Inheritance and Casting
Lesson 1 Implementing Inheritance Exercise 7: Implement Inheritance
106 115
Lesson 2 Implementing Upcasts Using Inheritance Exercise 8: Implement Upcasts
125 127
Lesson 3 Implementing Polymorphism Using Inheritance Exercise 9: Implement Polymorphism Using Inheritance
132 137
Lesson 4 Implementing Downcasts Using Inheritance Exercise 10: Implement Downcasts
144 147
UNIT OBJECTIVES ●
Explain generalization and specialization
●
Implement inheritance
●
Access elements of classes in inheritance
●
Implement upcasts using inheritance
●
Explain polymorphism
●
Implement polymorphism using inheritance
●
Implement downcasts using inheritance
●
Model class hierarchies
© Copyright. All rights reserved.
105
Unit 3 Lesson 1 Implementing Inheritance
LESSON OVERVIEW This lesson explains the concept of inheritance and its implementation. Business Example As a developer, you need to implement inheritance for the class in your ABAP objects project. For this reason, you require the following knowledge: ●
An understanding of inheritance
●
An understanding of Generalization and Specialization
LESSON OBJECTIVES After completing this lesson, you will be able to: ●
Explain generalization and specialization
●
Implement inheritance
●
Access elements of classes in inheritance
Generalization and Specialization
Figure 61: Example of Generalization and Specialization
Specialization describes a relationship in which one class (subclass) inherits all the main characteristics of another class (superclass). The subclass can also add new components (attributes, methods, and so on) and replace the implementations in inherited methods. In the
106
© Copyright. All rights reserved.
Lesson: Implementing Inheritance
latter case, the method name in the Unified Modeling Language (UML) diagram is renamed within the subclass. Specialization is an implementation relationship that emphasizes the similarities of the classes. In the above example, the common components of classes LCL_CAR, LCL_TRUCK, and LCL_BUS are defined in the UML model in the superclass, LCL_VEHICLE. The common components of the subclasses only need to be defined and implemented in the superclass and they are inherited by all the subclasses. Specialization is described as an "is a" relationship semantically. For example, a truck is a specific vehicle. Reversing the point of view is referred to as generalization. Characteristics of Generalization and Specialization
Figure 62: Characteristics of Generalization/Specialization
Generalization and specialization provides a significantly better structure for your software because commonly used elements only need to be stored once in a central location (in the superclass). These elements are then automatically available to all subclasses. Changes made at a later stage have an immediate effect on the subclasses. Therefore, do not alter the semantics when you change a superclass. You need knowledge of the implementation of the superclass to decide whether the inherited components from the superclass are sufficient for the subclass or if they must be extended. Generalization/specialization, therefore, provides strong links between the superclass and the subclass. When you develop additional subclasses, adapt the superclasses, too. The creation of a subclass sometimes leads to additional requirements for the superclass. For example, when a subclass requires certain protected components, or, when the details of implementation of superclass are required to change because of the method implementations in subclasses. The developer of superclass cannot predict all the requirements that subclasses need from the superclass.
© Copyright. All rights reserved.
107
Unit 3: Inheritance and Casting
Implementation of Inheritance
Figure 63: Inheritance – Syntax
In ABAP Objects, an inheritance relationship is defined for a subclass using the INHERITING FROM addition, followed by the superclass directly above the subclass. Usually, inheritance hierarchies of varying complexity can be created when a superclass inherits from another superclass, but, there is no multiple inheritance in ABAP Objects, that is, only one superclass can be specified directly above a class. However, you can use interfaces in ABAP Objects to simulate multiple inheritance. Inheritance must be used to implement generalization and specialization relationships. A superclass is a generalization of its subclasses. The subclasses are in turn different specializations of their superclasses. Thus, additions or changes are permitted in the subclasses but you can never remove anything from a superclass in a subclass. Inheritance is a one-sided relationship, subclasses recognize their direct superclasses but superclasses do not recognize their subclasses. In this example, the subclass also contains the set_type method. The subclass also defines the get_cargo method.
108
© Copyright. All rights reserved.
Lesson: Implementing Inheritance
Redefinition of Methods
Figure 64: Redefining Methods
Redefinition is when the implementation of an inherited instance method is changed for the subclass, without changing the signature. Because the visibility section for the superclass must remain the same, therefore, redefinition is not possible within the PRIVATE SECTION. When you use the REDEFINITION addition, you will specify a new implementation for the inherited method. Since the signature may not be changed, you do not need to define the method parameters and exceptions again. Within the redefined implementation of the method, you can use the predefined prefix “super->...” to access components in the superclass. You may need to do this when redefining a method to call the original method of the superclass. Preserving Semantics During Redefinition
Figure 65: Preserving Semantics During Redefinition
© Copyright. All rights reserved.
109
Unit 3: Inheritance and Casting
In the figure Preserving Semantics During Redefinition, the two redefined methods provide completely different information. The semantics of the method remains the same.
Subclass Constructors
Figure 66: Definition of the Constructor in Subclasses
A redefinition, as described for the methods in the figure Definition of the Constructor in Subclasses, would not be useful in the case of the constructor. In the subclass, either the constructor of the superclass can be used without any changes or the subclass has been expanded and the new parameters are now required in the constructors signature. In ABAP Objects, the constructor is not inherited like normal methods. Any class can define its own constructor that is fully independent from the definition of the constructor in its superclass. A subclass can even define a constructor if there is no constructor in the superclass. However, when implementing the subclass constructor, it is mandatory to call the constructor of the immediate superclass. By doing so, it is ensured that the constructor of class is always executed, whether the created object is an instance of the class itself, or an instance of one of its subclasses. Because of this enforced call of the superclass constructor, the subclass constructor generally adds parameters to the signature of the superclass constructor rather than completely changing it.
Hint: In this context, the concept of overloading is of relevance. With overloading, a method can have several definitions with different signatures and different implementations. The concept of overloading is not supported in ABAP Objects. The usual work-around is one signature with different sets of optional parameters.
110
© Copyright. All rights reserved.
Lesson: Implementing Inheritance
In contrast to instance constructors, the runtime environment automatically ensures that the static constructors of all its superclasses have already been executed before the static constructor in a particular class is executed in the runtime system. Rules for Calling the Constructor
Figure 67: Rules for Calling the Constructor
If a subclass has not changed its instance constructor, the constructor is adopted from the superclass. The implementation is also inherited from the superclass.
Inheritance and Visibility
Figure 68: Inheritance and Visibility
© Copyright. All rights reserved.
111
Unit 3: Inheritance and Casting
Inheritance provides an extension of the visibility concept through protected components (PROTECTED SECTION). The visibility of protected components lies between public and private components. Protected components are visible to all subclasses and the class itself. When defining local classes in ABAP Objects, follow the syntactical sequence of the PUBLIC SECTION, the PROTECTED SECTION, and the PRIVATE SECTION. Visibility Section – Protected Versus Private
Figure 69: Protected Versus Private Section
The components inherited from the superclass may not be visible in the subclass. A subclass can receive private components from its superclass which cannot be addressd in the syntax of the subclass. Private components of superclasses can only be addressed indirectly using public or protected methods from the superclass, which in turn, can access the private attributes. These restrictions are necessary to ensure that centralized maintenance is possible. In this example, it is possible to access the protected constant C_POS_1 in superclass LCL_VEHICLE directly from its subclass LCL_BUS. On the other hand, the only way to access the private MV_MAKE and MV_MODEL attributes from the subclasses of LCL_VEHICLE is to call methods of LCL_VEHICLE. These methods have to be public or protected. Using the PRIVATE SECTION, you can change superclasses without the need to know the subclasses. As long as the changes you make do not affect the semantics, you do not need to adapt the subclasses. This is because they only indirectly access the private components from the superclass.
Inheritance and Static Components Summary of static components and inheritance are as follows: ●
●
112
A class that defines a public or protected static attribute shares this attribute with all its subclasses. Static methods cannot be redefined.
© Copyright. All rights reserved.
Lesson: Implementing Inheritance
●
●
●
The static constructor of a superclass is executed when the superclass or one of its subclasses is accessed for the first time. A subclass can always have a static constructor irrespective of the superclass. If a subclass and its superclass both have a static constructor then both constructors are executed when we access the subclass for the first time. In the case access to the superclass and subclass static constructor occurs at the same time, the superclass static constructor will execute first immediately followed by the subclass static constructor.
© Copyright. All rights reserved.
113
Unit 3: Inheritance and Casting
114
© Copyright. All rights reserved.
Unit 3 Exercise 7 Implement Inheritance
Business Example You must refine your airplane management program. Create classes for specific airplanes in relation to a general airplane class.
Note: This exercise uses the main program file ZBC401_##_MAIN completed in the previous exercise. If not complete, copy the model solution from the previous exercise. In the exercises for this course, when the input values include ##, replace ## with your group number. Template SAPBC401_BAS_S5 Solution SAPBC401_INH_S1 Define a Specialized Passenger Plane Class Define the local class LCL_PASSENGER_PLANE for passenger planes. Define the class as a subclass of LCL_AIRPLANE. Add specific attributes and methods and redefine the DISPLAY_ATTRIBUTES method. 1. Define a new local class LCL_PASSENGER_PLANE and make it a subclass of the already existing LCL_AIRPLANE. 2. Is there a specific sequence in which you have to define the classes in the source code?
3. The class must have a private instance attribute, MV_SEATS, with the same type as the table field SAPLANE-SEATSMAX. 4. Define and implement an instance constructor that assigns values to all instance attributes in the class. 5. Redefine method DISPLAY_ATTRIBUTES so that all instance attributes are displayed using the WRITE statement. Make sure the output of specific attributes are aligned with the output from the superclass. Therefore, change the visibility of the C_POS_1 constant so that you can use it in your subclass. Define a Specialized Cargo Plane Class In the class LCL_AIRPLANE, define the local subclass LCL_CARGO_PLANE for cargo planes.
© Copyright. All rights reserved.
115
Unit 3: Inheritance and Casting
1. The class must have a private instance attribute, MV_CARGO , with the same type as the table field SCPLANE-CARGOMAX . 2. Define and implement an instance constructor that assigns values to all instance attributes in the class. 3. Redefine DISPLAY_ATTRIBUTES so that all instance attributes are displayed using the WRITE statement. Instantiate the New Classes Create instances of your new classes and display their attributes. 1. In the main program, define a suitably typed reference variable for each of your new classes. 2. Before instantiating any objects, call the static method DISPLAY_N_O_AIRPLANES. 3. Use the two references to create an instance of each of the subclasses LCL_PASSENGER_PLANE and LCL_CARGO_PLANE. Decide for yourself how to fill the attributes. 4. Call the DISPLAY_ATTRIBUTES method for both instances. 5. Save, check, and activate your program. Analyze Your Program With the Debugger Debug your program. 1. Could the method GET_TECHNICAL_ATTRIBUTES be called directly from the redefined method DISPLAY_ATTRIBUTES of the subclasses?
2. Observe the program flow in the ABAP Debugger, paying special attention to the call of the DISPLAY_ATTRIBUTES method.
116
© Copyright. All rights reserved.
Unit 3 Solution 7 Implement Inheritance
Business Example You must refine your airplane management program. Create classes for specific airplanes in relation to a general airplane class.
Note: This exercise uses the main program file ZBC401_##_MAIN completed in the previous exercise. If not complete, copy the model solution from the previous exercise. In the exercises for this course, when the input values include ##, replace ## with your group number. Template SAPBC401_BAS_S5 Solution SAPBC401_INH_S1 Define a Specialized Passenger Plane Class Define the local class LCL_PASSENGER_PLANE for passenger planes. Define the class as a subclass of LCL_AIRPLANE. Add specific attributes and methods and redefine the DISPLAY_ATTRIBUTES method. 1. Define a new local class LCL_PASSENGER_PLANE and make it a subclass of the already existing LCL_AIRPLANE. a) See the source code extract from the model solution. 2. Is there a specific sequence in which you have to define the classes in the source code? A superclass has to be defined first. Otherwise, the syntax check will not know it when you refer to superclass in the INHERITING FROM part of the subclass definition. 3. The class must have a private instance attribute, MV_SEATS, with the same type as the table field SAPLANE-SEATSMAX. a) See the source code extract from the model solution. 4. Define and implement an instance constructor that assigns values to all instance attributes in the class. a) See the source code extract from the model solution. 5. Redefine method DISPLAY_ATTRIBUTES so that all instance attributes are displayed using the WRITE statement.
© Copyright. All rights reserved.
117
Unit 3: Inheritance and Casting
Make sure the output of specific attributes are aligned with the output from the superclass. Therefore, change the visibility of the C_POS_1 constant so that you can use it in your subclass. a) See the source code extract from the model solution. Define a Specialized Cargo Plane Class In the class LCL_AIRPLANE, define the local subclass LCL_CARGO_PLANE for cargo planes. 1. The class must have a private instance attribute, MV_CARGO , with the same type as the table field SCPLANE-CARGOMAX . a) See the source code extract from the model solution. 2. Define and implement an instance constructor that assigns values to all instance attributes in the class. a) See the source code extract from the model solution. 3. Redefine DISPLAY_ATTRIBUTES so that all instance attributes are displayed using the WRITE statement. a) See the source code extract from the model solution. Instantiate the New Classes Create instances of your new classes and display their attributes. 1. In the main program, define a suitably typed reference variable for each of your new classes. a) See the source code extract from the model solution. 2. Before instantiating any objects, call the static method DISPLAY_N_O_AIRPLANES. a) See the source code extract from the model solution. 3. Use the two references to create an instance of each of the subclasses LCL_PASSENGER_PLANE and LCL_CARGO_PLANE. Decide for yourself how to fill the attributes. a) See the source code extract from the model solution. 4. Call the DISPLAY_ATTRIBUTES method for both instances. a) See the source code extract from the model solution. 5. Save, check, and activate your program. a) Save your program. b) To check your program, on the application toolbar choose the Check button. c) To activate your program, on the application toolbar choose the Activate button. Analyze Your Program With the Debugger Debug your program. 1. Could the method GET_TECHNICAL_ATTRIBUTES be called directly from the redefined method DISPLAY_ATTRIBUTES of the subclasses? No, because the method is private in the superclass.
118
© Copyright. All rights reserved.
Lesson: Implementing Inheritance
2. Observe the program flow in the ABAP Debugger, paying special attention to the call of the DISPLAY_ATTRIBUTES method. a) To start the ABAP Debugger, choose Program → Execute → Debugging. b) To debug your program, on the application toolbar choose the Execute button, or press F8. Solution: SAPBC401_INH_S1 REPORT
sapbc401_inh_s1.
TYPE-POOLS icon. *------------------------------------------------* * CLASS lcl_airplane DEFINITION *------------------------------------------------* CLASS lcl_airplane DEFINITION. PUBLIC SECTION. METHODS: constructor IMPORTING iv_name TYPE string iv_planetype TYPE saplane-planetype EXCEPTIONS wrong_planetype, display_attributes. CLASS-METHODS: class_constructor, display_n_o_airplanes, get_n_o_airplanes RETURNING value(rv_count) TYPE i. PROTECTED SECTION. CONSTANTS: c_pos_1 TYPE i VALUE 30. PRIVATE SECTION. TYPES: ty_planetypes TYPE STANDARD TABLE OF saplane WITH NON-UNIQUE KEY planetype. DATA: mv_name mv_planetype mv_weight mv_tankcap
TYPE TYPE TYPE TYPE
string, saplane-planetype, saplane-weight, saplane-tankcap.
CLASS-DATA: gv_n_o_airplanes TYPE i, gt_planetypes TYPE ty_planetypes. CLASS-METHODS: get_technical_attributes IMPORTING iv_type TYPE saplane-planetype EXPORTING ev_weight TYPE saplane-weight ev_tankcap TYPE saplane-tankcap
© Copyright. All rights reserved.
119
Unit 3: Inheritance and Casting
EXCEPTIONS wrong_planetype. ENDCLASS.
"lcl_airplane DEFINITION
*-------------------------------------------------* * CLASS lcl_airplane IMPLEMENTATION *-------------------------------------------------* CLASS lcl_airplane IMPLEMENTATION. METHOD class_constructor. SELECT * FROM saplane INTO TABLE gt_planetypes. ENDMETHOD. "class_constructor METHOD constructor. mv_name = iv_name. mv_planetype = iv_planetype. get_technical_attributes( EXPORTING iv_type = iv_planetype IMPORTING ev_weight = mv_weight ev_tankcap = mv_tankcap EXCEPTIONS wrong_planetype = 1 ). IF sy-subrc <> 0. RAISE wrong_planetype. ELSE. gv_n_o_airplanes = gv_n_o_airplanes + 1. ENDIF. ENDMETHOD.
"constructor
METHOD display_attributes. WRITE: / icon_ws_plane AS ICON, / 'Name of Airplane'(001) , / 'Type of Airplane:'(002), / 'Weight:'(003), LEFT-JUSTIFIED, / 'Tank capacity:'(004), LEFT-JUSTIFIED. ENDMETHOD.
AT c_pos_1 mv_name, AT c_pos_1 mv_planetype, AT c_pos_1 mv_weight AT c_pos_1 mv_tankcap
"display_attributes
METHOD display_n_o_airplanes. SKIP. WRITE: / 'Number of airplanes:'(ca1), AT c_pos_1 gv_n_o_airplanes LEFT-JUSTIFIED. ENDMETHOD. "display_n_o_airplanes METHOD get_n_o_airplanes. rv_count = gv_n_o_airplanes. ENDMETHOD. "get_n_o_airplanes METHOD get_technical_attributes. DATA: ls_planetype TYPE saplane.
120
© Copyright. All rights reserved.
Lesson: Implementing Inheritance
READ TABLE gt_planetypes INTO ls_planetype WITH TABLE KEY planetype = iv_type TRANSPORTING weight tankcap. IF sy-subrc = 0. ev_weight = ls_planetype-weight. ev_tankcap = ls_planetype-tankcap. ELSE. RAISE wrong_planetype. ENDIF. ENDMETHOD. "get_technical_attributes ENDCLASS.
"lcl_airplane IMPLEMENTATION
*------------------------------------------------* * CLASS lcl_cargo_plane DEFINITION *------------------------------------------------* CLASS lcl_cargo_plane DEFINITION INHERITING FROM lcl_airplane. PUBLIC SECTION. METHODS: constructor IMPORTING iv_name TYPE string iv_planetype TYPE saplane-planetype iv_cargo TYPE s_plan_car EXCEPTIONS wrong_planetype, display_attributes REDEFINITION. PRIVATE SECTION. DATA: mv_cargo TYPE s_plan_car. ENDCLASS.
"lcl_cargo_plane DEFINITION
*------------------------------------------------* * CLASS lcl_cargo_plane IMPLEMENTATION *------------------------------------------------* CLASS lcl_cargo_plane IMPLEMENTATION. METHOD constructor. super->constructor( EXPORTING iv_name = iv_name iv_planetype = iv_planetype EXCEPTIONS wrong_planetype = 1 ). IF sy-subrc <> 0. RAISE wrong_planetype. ENDIF. mv_cargo = iv_cargo. ENDMETHOD. "constructor METHOD display_attributes. super->display_attributes( ).
© Copyright. All rights reserved.
121
Unit 3: Inheritance and Casting
WRITE: / 'Max Cargo:'(005), AT c_pos_1 mv_cargo LEFT-JUSTIFIED. ULINE. ENDMETHOD. "display_attributes ENDCLASS.
"lcl_cargo_plane IMPLEMENTATION
*------------------------------------------------* * CLASS lcl_passenger_plane DEFINITION *------------------------------------------------* CLASS lcl_passenger_plane DEFINITION INHERITING FROM lcl_airplane. PUBLIC SECTION. METHODS: constructor IMPORTING iv_name TYPE string iv_planetype TYPE saplane-planetype iv_seats TYPE s_seatsmax EXCEPTIONS wrong_planetype, display_attributes REDEFINITION. PRIVATE SECTION. DATA: mv_seats TYPE s_seatsmax. ENDCLASS.
"lcl_passenger_plane DEFINITION
*------------------------------------------------* * CLASS lcl_passenger_plane IMPLEMENTATION *------------------------------------------------* CLASS lcl_passenger_plane IMPLEMENTATION. METHOD constructor. super->constructor( EXPORTING iv_name = iv_name iv_planetype = iv_planetype EXCEPTIONS wrong_planetype = 1 ). IF sy-subrc <> 0. RAISE wrong_planetype. ENDIF. mv_seats = iv_seats. ENDMETHOD. "constructor METHOD display_attributes. super->display_attributes( ). WRITE: / 'Max Seats:'(006), AT c_pos_1 mv_seats LEFT-JUSTIFIED. ULINE. ENDMETHOD. "display_attributes ENDCLASS. "lcl_passenger_plane IMPLEMENTATION DATA:
122
© Copyright. All rights reserved.
Lesson: Implementing Inheritance
go_airplane go_cargo go_passenger gt_airplanes gv_count
TYPE TYPE TYPE TYPE TYPE
REF TO lcl_airplane, REF TO lcl_cargo_plane, REF TO lcl_passenger_plane, TABLE OF REF TO lcl_airplane, i.
START-OF-SELECTION. ******************* lcl_airplane=>display_n_o_airplanes( ). CREATE OBJECT go_passenger EXPORTING iv_name = 'LH BERLIN' iv_planetype = '747-400' iv_seats = 345 EXCEPTIONS wrong_planetype = 1. IF sy-subrc = 0. * do nothing for now ENDIF. CREATE OBJECT go_cargo EXPORTING iv_name = 'US Hercules' iv_planetype = '747-200F' iv_cargo = 533 EXCEPTIONS wrong_planetype = 1. IF sy-subrc = 0. * do nothing just now ENDIF. go_passenger->display_attributes( ). go_cargo->display_attributes( ). gv_count = lcl_airplane=>get_n_o_airplanes( ). SKIP 2. WRITE: / 'Number of airplanes'(ca1), gv_count.
© Copyright. All rights reserved.
123
Unit 3: Inheritance and Casting
LESSON SUMMARY You should now be able to:
124
●
Explain generalization and specialization
●
Implement inheritance
●
Access elements of classes in inheritance
© Copyright. All rights reserved.
Unit 3 Lesson 2 Implementing Upcasts Using Inheritance
LESSON OVERVIEW This lesson explains the concept of up-casts and the dynamic and the static type of reference variable. This lesson also explains the method of implementing up-casts. Business Example As a developer, you need to implement the upcast concept for your ABAP object classes. For this reason, you require the following knowledge: ●
An understanding of inheritance
●
An understanding of upcasts
LESSON OBJECTIVES After completing this lesson, you will be able to: ●
Implement upcasts using inheritance
Upcasts
Figure 70: Up-Cast (Widening Cast) with Object References
If you assign a subclass reference to a superclass reference, this subclass ensures that all components that you can access syntactically after the cast assignment are actually available in the instance. The subclass always contains at least the same components as the superclass always the name and the signature of redefined methods are identical. The user can address only those methods and attributes from the subclass instance that they can from the superclass instance.
© Copyright. All rights reserved.
125
Unit 3: Inheritance and Casting
Hint: Note that with redefined methods, the implementation of the subclass is executed using the superclass static type of reference. In this example, after the assignment, you can only access the methods GET_MAKE, GET_COUNT, DISPLAY_ATTRIBUTES, SET_ATTRIBUTES, and ESTIMATE_FUEL of the instance LCL_TRUCK by using the reference GO_VEHICLE. If there are any restrictions regarding visibility, they are left unchanged. It is not possible to access the specific components from the class LCL_TRUCK of the instance GET_CARGO in the example using the reference GO_VEHICLE. The view or possible access to methods is either narrowed or left unchanged. There is a switch from a view of several components to a view of a few components. As the target variable can accept more dynamic types in comparison to the source variable, this assignment is also called widening cast.
Static and Dynamic Type
Figure 71: Static and Dynamic Types of References
Types of a reference variable at runtime in object oriented programming: ●
Static
●
Dynamic
In the example, LCL_VEHICLE is the static type of the variable GO_VEHICLE. Depending on the cast assignment, the dynamic type is either LCL_BUS or LCL_TRUCK. In the ABAP Debugger, the dynamic type is specified in the following form: object_id<\PROGRAM=program_name\CLASS=dynamic_type>
Note: Assignments between reference variables are possible whenever the static type of the target variables is more general or equal to the dynamic type of the source variables.
126
© Copyright. All rights reserved.
Unit 3 Exercise 8 Implement Upcasts
Business Example As a developer, your airplane management program should display the attributes of the airplane objects generically, that is, it should be open to future extensions with additional airplane classes. Template SAPBC401_INH_S1 Solution SAPBC401_INH_S2 Buffer References in an Internal Table Buffer the airplane references in a suitable type of internal table. 1. Complete your program ZBC401_##_MAIN (where ## is your two-digit group number) or copy the sample solution program from the previous exercise. 2. In your main program, define an internal table for buffering airplane references if you do not already have one. The row type of the internal table should be REF TO LCL_AIRPLANE. Display the Attributes of all Airplane Types Created Display the attributes of all airplane types that were created so far. 1. Insert the references to your passenger and cargo airplanes into the internal table. 2. Program a loop through the contents of the internal table. Call the DISPLAY_ATTRIBUTES method every time the loop runs. Analyze the Program Analyze your program. 1. What would happen if the method DISPLAY_ATTRIBUTES had not been redefined in the subclasses?
2. Follow the program flow in the ABAP Debugger, paying special attention to the call of the method DISPLAY_ATTRIBUTES.
© Copyright. All rights reserved.
127
Unit 3 Solution 8 Implement Upcasts
Business Example As a developer, your airplane management program should display the attributes of the airplane objects generically, that is, it should be open to future extensions with additional airplane classes. Template SAPBC401_INH_S1 Solution SAPBC401_INH_S2 Buffer References in an Internal Table Buffer the airplane references in a suitable type of internal table. 1. Complete your program ZBC401_##_MAIN (where ## is your two-digit group number) or copy the sample solution program from the previous exercise. a) Carry out this step as usual. Additional information is available in the SAP Library. 2. In your main program, define an internal table for buffering airplane references if you do not already have one. The row type of the internal table should be REF TO LCL_AIRPLANE. a) See the source code extract from the model solution. Display the Attributes of all Airplane Types Created Display the attributes of all airplane types that were created so far. 1. Insert the references to your passenger and cargo airplanes into the internal table. a) See the source code extract from the model solution. 2. Program a loop through the contents of the internal table. Call the DISPLAY_ATTRIBUTES method every time the loop runs. a) See the source code extract from the model solution. Analyze the Program Analyze your program. 1. What would happen if the method DISPLAY_ATTRIBUTES had not been redefined in the subclasses? The implementation from the superclass would be executed. Your program would not contain polymorphism. 2. Follow the program flow in the ABAP Debugger, paying special attention to the call of the method DISPLAY_ATTRIBUTES. a) Carry out this step as usual. Additional information is available in the SAP Library.
128
© Copyright. All rights reserved.
Lesson: Implementing Upcasts Using Inheritance
Solution: SAPBC401_INH_S2 REPORT sapbc401_inh_s2. TYPE-POOLS icon. *-----------------------------------------------* * CLASS lcl_airplane DEFINITION *-----------------------------------------------* CLASS lcl_airplane DEFINITION. ... ENDCLASS. "lcl_airplane DEFINITION *-----------------------------------------------* * CLASS lcl_airplane IMPLEMENTATION *-----------------------------------------------* CLASS lcl_airplane IMPLEMENTATION. ... ENDCLASS. "lcl_airplane IMPLEMENTATION *-----------------------------------------------* * CLASS lcl_cargo_plane DEFINITION *-----------------------------------------------* CLASS lcl_cargo_plane DEFINITION INHERITING FROM lcl_airplane. ... ENDCLASS. "lcl_cargo_plane DEFINITION *-----------------------------------------------* *CLASS lcl_cargo_plane IMPLEMENTATION *-----------------------------------------------* CLASS lcl_cargo_plane IMPLEMENTATION. ... ENDCLASS. "lcl_cargo_plane IMPLEMENTATION *-----------------------------------------------* * CLASS lcl_passenger_plane DEFINITION *-----------------------------------------------* CLASS lcl_passenger_plane DEFINITION INHERITING FROM lcl_airplane. ... ENDCLASS. "lcl_passenger_plane DEFINITION *-----------------------------------------------* * CLASS lcl_passenger_plane IMPLEMENTATION *-----------------------------------------------* CLASS lcl_passenger_plane IMPLEMENTATION. ... ENDCLASS. "lcl_passenger_plane IMPLEMENTATION DATA: go_airplane TYPE REF TO lcl_airplane, go_cargo TYPE REF TO lcl_cargo_plane, go_passenger TYPE REF TO lcl_passenger_plane, gt_airplanes TYPE TABLE OF REF TO lcl_airplane, gv_count TYPE i.
START-OF-SELECTION. ******************* lcl_airplane=>display_n_o_airplanes( ).
© Copyright. All rights reserved.
129
Unit 3: Inheritance and Casting
CREATE OBJECT go_passenger EXPORTING iv_name = 'LH BERLIN' iv_planetype = '747-400' iv_seats = 345 EXCEPTIONS wrong_planetype = 1. IF sy-subrc = 0. APPEND go_passenger TO gt_airplanes. ENDIF. CREATE OBJECT go_cargo EXPORTING iv_name = 'US Hercules' iv_planetype = '747-200F' iv_cargo = 533 EXCEPTIONS wrong_planetype = 1. IF sy-subrc = 0. APPEND go_cargo TO gt_airplanes. ENDIF. LOOP AT gt_airplanes INTO go_airplane. go_airplane->display_attributes( ). ENDLOOP. gv_count = lcl_airplane=>get_n_o_airplanes( ). SKIP 2. WRITE: / 'Number of airplanes'(ca1), gv_count.
130
© Copyright. All rights reserved.
Lesson: Implementing Upcasts Using Inheritance
LESSON SUMMARY You should now be able to: ●
Implement upcasts using inheritance
© Copyright. All rights reserved.
131
Unit 3 Lesson 3 Implementing Polymorphism Using Inheritance
LESSON OVERVIEW This lesson explains polymorphism and implementing polymorphism using inheritance. Business Example As a developer, you need to implement polymorphism using inheritance. For this reason, you require the following knowledge: ●
An understanding of polymorphism
●
An understanding of generic access and upcast assignments
LESSON OBJECTIVES After completing this lesson, you will be able to: ●
Explain polymorphism
●
Implement polymorphism using inheritance
Generic Access to Objects
Figure 72: Generic Access After Up-Cast Assignments
A typical use for up-cast assignments is to prepare for generic access. A user who is not interested in the finer points of the instances of the subclasses but simply needs to address the shared components can use a superclass reference for this access. In the example, a travel agency LCL_RENTAL needs to manage all imaginable kinds of vehicles in one list. To manage all these vehicles in one list, create an internal table and assign
132
© Copyright. All rights reserved.
Lesson: Implementing Polymorphism Using Inheritance
it with an appropriate type for the references to the vehicle instances. The car rental company also needs to be able to calculate the required amount of fuel for all its vehicles. In this case, the DISPLAY_ATTRIBUTES method which is defined in the superclass LCL_VEHICLE must be redefined in all subclasses. Row Type of the Internal Table in the Application – Example
Figure 73: Row Type of the Internal Table in the Application – Example
When objects of different classes (LCL_BUS, LCL_TRUCK and LCL_CAR) are specified as type superclass references (LCL_VEHICLE), these objects can be stored in an internal table. The shared components of the subclass objects can then be accessed uniformly. For this example, you need the method ADD_VEHICLE to copy the references to the vehicle types into the internal table. The import parameter of this method is already typed as the reference to the superclass. Up-Cast and Generic Access in the Application – Example
Figure 74: Up-Cast and Generic Access in the Application – Example
© Copyright. All rights reserved.
133
Unit 3: Inheritance and Casting
In this example, the up-cast assignment occurs when the vehicle reference is transferred to the formal parameter of ADD_VEHICLE method. The shared component is generically accessed within the loop around the internal table containing all of the vehicle references. The DISPLAY_ATTRIBUTES method was inherited from the LCL_VEHICLE superclass and may have been redefined.
Polymorphism
Figure 75: Polymorphism – Generic Access Using the Superclass Reference
The implementation to be executed when DISPLAY_ATTRIBUTES is called will depend on which object the superclass reference LO_VEHICLE refers to. The dynamic type (not the static type) of the reference variable is used to search for the implementation of a method. Therefore, when lo_vehicle->display_attributes is called, the implementation is not executed from LCL_VEHICLE (static type of LO_VEHICLE) because the method was redefined in all vehicle classes. When an instance receives a message to execute a particular method, the method that implemented the class of this instance is executed. If the class has not been redefined in the method, the implementation from the superclass is executed. Characteristics of Polymorphism When objects from different classes react differently to the same method calls, this is known as polymorphism. The possibility of polymorphism is one of the main strengths of inheritance. A client can handle different classes uniformly, irrespective of their implementation. The runtime system searches for the right implementation of a method on behalf of the client. Polymorphism can be used to write programs that are highly generic, that is, they do not need to be changed significantly if use cases are added. For instance, polymorphism may make it very easy to add motorbikes to this example. You simply need to define a new subclass of LCL_VEHICLE, which you can call LCL_MOTORBIKE. You would also have to redefine the inherited method DISPLAY_ATTRIBUTES. Without needing any more changes, your vehicle management system can then work with motorbikes, as well as, calculate the required fuel levels for them.
134
© Copyright. All rights reserved.
Lesson: Implementing Polymorphism Using Inheritance
Generic Calls in the Procedural Programming Model
Figure 76: Generic Calls in the Procedural Programming Model
Using dynamic function module calls, you can program generically in ABAP, even without an object-oriented programming model. When you compare dynamic function module call with polymorphism through inheritance, the source code is less self-explanatory and is more susceptible to errors in dynamic function module call. For example, the syntax check can only check whether the function module is called correctly or not. The syntax check cannot check whether the internal table contains a valid function module name for each vehicle or not.
© Copyright. All rights reserved.
135
Unit 3: Inheritance and Casting
136
© Copyright. All rights reserved.
Unit 3 Exercise 9 Implement Polymorphism Using Inheritance
Business Example You need to encapsulate the management of airplane instances in a new class instead of the main program. Template SAPBC401_INH_T3 Solution SAPBC401_INH_S3 Define a Local Class Define a local class for airlines. 1. Complete your program ZBC401_##_MAIN (where ## is your two-digit group number) or copy the template program. If you copy the template program then you can go directly to the next step. Otherwise, copy the local class LCL_CARRIER along with the definition and implementation of the class from the template program and paste it into your own program. 2. Define a private instance attribute MT_AIRPLANES to store references to airplanes. 3. Define and implement a public method ADD_AIRPLANE so that airplane references can be added to the previously defined list MT_AIRPLANES. The method should have one import parameter that is IO_PLANE. 4. Define and implement a private instance method DISPLAY_AIRPLANES. In this method, loop at the list of airplanes and call method DISPLAY_ATTRIBUTES for each airplane. 5. Extend the implementation of the method DISPLAY_ATTRIBUTES in a way that not only the information about the carrier itself is displayed but also all its airplanes. Use the previously defined method DISPLAY_AIRPLANES.
Create an Instance and Transfer References to the Instance In the main program, create an airline instance. Transfer some airplane references to the airline instance and display the attributes. 1. Remove all the statements from the main program that define the global internal table for airplane references and their insertions. 2. In the main program, define a suitably typed reference variable for your new airline class. 3. Using the reference, generate an instance of your class LCL_CARRIER. Decide for yourself how to fill the attributes.
© Copyright. All rights reserved.
137
Unit 3: Inheritance and Casting
4. Call the method ADD_AIRPLANE to transfer each airplane instance to the carrier. You may also create and transfer additional airplanes. 5. Display the attributes of the airline by calling its method DISPLAY_ATTRIBUTES.
138
© Copyright. All rights reserved.
Unit 3 Solution 9 Implement Polymorphism Using Inheritance
Business Example You need to encapsulate the management of airplane instances in a new class instead of the main program. Template SAPBC401_INH_T3 Solution SAPBC401_INH_S3 Define a Local Class Define a local class for airlines. 1. Complete your program ZBC401_##_MAIN (where ## is your two-digit group number) or copy the template program. If you copy the template program then you can go directly to the next step. Otherwise, copy the local class LCL_CARRIER along with the definition and implementation of the class from the template program and paste it into your own program. a) Carry out this step in the usual manner. Additional information is available in the SAP Library. b) Refer the source code extract from the model solution. 2. Define a private instance attribute MT_AIRPLANES to store references to airplanes. a) Refer the source code extract from the model solution. 3. Define and implement a public method ADD_AIRPLANE so that airplane references can be added to the previously defined list MT_AIRPLANES. The method should have one import parameter that is IO_PLANE. a) Refer the source code extract from the model solution. 4. Define and implement a private instance method DISPLAY_AIRPLANES. In this method, loop at the list of airplanes and call method DISPLAY_ATTRIBUTES for each airplane. a) Refer the source code extract from the model solution. 5. Extend the implementation of the method DISPLAY_ATTRIBUTES in a way that not only the information about the carrier itself is displayed but also all its airplanes. Use the previously defined method DISPLAY_AIRPLANES. a) Refer the source code extract from the model solution.
Create an Instance and Transfer References to the Instance In the main program, create an airline instance. Transfer some airplane references to the airline instance and display the attributes.
© Copyright. All rights reserved.
139
Unit 3: Inheritance and Casting
1. Remove all the statements from the main program that define the global internal table for airplane references and their insertions. a) Refer the source code extract from the model solution. 2. In the main program, define a suitably typed reference variable for your new airline class. a) Refer the source code extract from the model solution. 3. Using the reference, generate an instance of your class LCL_CARRIER. Decide for yourself how to fill the attributes. a) Refer the source code extract from the model solution. 4. Call the method ADD_AIRPLANE to transfer each airplane instance to the carrier. You may also create and transfer additional airplanes. a) Refer the source code extract from the model solution. 5. Display the attributes of the airline by calling its method DISPLAY_ATTRIBUTES. a) Refer the source code extract from the model solution. SAPBC401_INH_S3 REPORT sapbc401_inh_s3. TYPE-POOLS icon. *------------------------------------------------* * CLASS lcl_airplane DEFINITION *------------------------------------------------* CLASS lcl_airplane DEFINITION. ... ENDCLASS. "lcl_airplane DEFINITION *------------------------------------------------* * CLASS lcl_airplane IMPLEMENTATION *------------------------------------------------* CLASS lcl_airplane IMPLEMENTATION. ... ENDCLASS. "lcl_airplane IMPLEMENTATION *------------------------------------------------* * CLASS lcl_cargo_plane DEFINITION *------------------------------------------------* CLASS lcl_cargo_plane DEFINITION INHERITING FROM lcl_airplane. ... ENDCLASS. "lcl_cargo_plane DEFINITION *------------------------------------------------* * CLASS lcl_cargo_plane IMPLEMENTATION *------------------------------------------------* CLASS lcl_cargo_plane IMPLEMENTATION. ... ENDCLASS. "lcl_cargo_plane IMPLEMENTATION *------------------------------------------------* * CLASS lcl_passenger_plane DEFINITION *------------------------------------------------* CLASS lcl_passenger_plane DEFINITION INHERITING FROM lcl_airplane. ... ENDCLASS. "lcl_passenger_plane DEFINITION
140
© Copyright. All rights reserved.
Lesson: Implementing Polymorphism Using Inheritance
*------------------------------------------------* * CLASS lcl_passenger_plane IMPLEMENTATION *------------------------------------------------* CLASS lcl_passenger_plane IMPLEMENTATION. ... ENDCLASS. "lcl_passenger_plane IMPLEMENTATION *------------------------------------------------* * CLASS lcl_carrier DEFINITION *------------------------------------------------* CLASS lcl_carrier DEFINITION. PUBLIC SECTION. METHODS: constructor IMPORTING iv_name TYPE string, display_attributes, add_airplane IMPORTING io_plane TYPE REF TO lcl_airplane. PRIVATE SECTION. DATA: mv_name TYPE string, mt_airplanes TYPE TABLE OF REF TO lcl_airplane. METHODS: display_airplanes. ENDCLASS. "lcl_carrier DEFINITION *------------------------------------------------* * CLASS lcl_carrier IMPLEMENTATION *------------------------------------------------* CLASS lcl_carrier IMPLEMENTATION. METHOD constructor. mv_name = iv_name. ENDMETHOD. "constructor METHOD display_attributes. SKIP 2. WRITE: icon_flight AS ICON, mv_name. ULINE. ULINE. me->display_airplanes( ). ENDMETHOD. "display_attributes METHOD add_airplane. APPEND io_plane TO mt_airplanes. ENDMETHOD. "add_airplane METHOD display_airplanes. DATA: lo_plane TYPE REF TO lcl_airplane. LOOP AT mt_airplanes INTO lo_plane. lo_plane->display_attributes( ). ENDLOOP. ENDMETHOD. "display_airplanes ENDCLASS. "lcl_carrier IMPLEMENTATION DATA: go_carrier TYPE REF TO lcl_carrier, go_airplane TYPE REF TO lcl_airplane,
© Copyright. All rights reserved.
141
Unit 3: Inheritance and Casting
go_cargo TYPE REF TO lcl_cargo_plane, go_passenger TYPE REF TO lcl_passenger_plane, gv_count TYPE i. START-OF-SELECTION. ******************* ***** Create Carrier CREATE OBJECT go_carrier EXPORTING iv_name = 'Smile&Fly-Travel'. ***** Passenger Plane CREATE OBJECT go_passenger EXPORTING iv_name = 'LH BERLIN' iv_planetype = '747-400' iv_seats = 345 EXCEPTIONS wrong_planetype = 1. IF sy-subrc = 0. go_carrier->add_airplane( go_passenger ). ENDIF. ***** cargo Plane CREATE OBJECT go_cargo EXPORTING iv_name = 'US Hercules' iv_planetype = '747-200F' iv_cargo = 533 EXCEPTIONS wrong_planetype = 1. IF sy-subrc = 0. go_carrier->add_airplane( go_cargo ). ENDIF. ***** output carrier (including list of airplanes) go_carrier->display_attributes( ).
142
© Copyright. All rights reserved.
Lesson: Implementing Polymorphism Using Inheritance
LESSON SUMMARY You should now be able to: ●
Explain polymorphism
●
Implement polymorphism using inheritance
© Copyright. All rights reserved.
143
Unit 3 Lesson 4 Implementing Downcasts Using Inheritance
LESSON OVERVIEW This lesson explains the concept of downcast assignments (narrowing cast). Business Example As a developer, you need to create a subclass from the airplane class and then use casting to access different attributes. For this reason, you require the following knowledge: ●
An understanding of downcasts
●
An understanding of inheritance
●
An understanding of implementing downcasts using Inheritance
LESSON OBJECTIVES After completing this lesson, you will be able to: ●
Implement downcasts using inheritance
●
Model class hierarchies
Downcasts
Figure 77: Down-Cast (Narrowing-Cast) with Object References
Reference variables of the superclass can also refer to the subclass instances at runtime. You may copy this reference back to a reference variable of the subclass type.
144
© Copyright. All rights reserved.
Lesson: Implementing Downcasts Using Inheritance
To assign a superclass reference to a subclass reference, you must use the down-cast assignment operator MOVE ... ?TO ... or its short form ?=. Otherwise, you get a message stating that it is not certain that all the components that can be accessed syntactically after the cast assignment are actually available in the instance. As a rule, the subclass contains more components than the superclass. After assigning this type of reference back to a subclass reference to the implementing class, clients are no longer limited to inherited components. In the example shown in the figure Down-Cast (Narrowing-Cast) with Object References, all the components of the LCL_TRUCK instance can be accessed again after the assignment using the GO_TRUCK2 reference. Therefore, usually the view is either widened or not changed. This type of assignment of reference variables is known as down-cast. There is a switch from a view of a few components to a view of many components. As the target variable can accept less dynamic types after the assignment, this assignment is also called narrowing cast. Specific Access After Down-Cast Assignments
Figure 78: Specific Access After Down-Cast Assignments
Down-cast assignments are used when you need to address specific components of instances and keep the references of these components in variables that are typed on the superclass. A user who is interested in the finer points of the instances of a subclass cannot use the superclass reference for this access because it allows access only to the shared components.
© Copyright. All rights reserved.
145
Unit 3: Inheritance and Casting
Exceptions Handling for Downcasts
Figure 79: Down-Cast and Exception Handling in the Application - Example
In this example, a car rental company (LCL_RENTAL) has to determine the maximum capacity of its trucks, but it stores all types of vehicle references in an internal table LCL_VEHICLE. There may be a problem if there is no truck reference in the LO_VEHICLE superclass reference at runtime but the down-cast assignment operator tries to copy the reference to the now invalid reference LO_TRUCK. In contrast to the up-cast assignment, it is possible that the static type of the target variable (LO_TRUCK) is no more general than nor is the same as the dynamic type of the source variable (LO_VEHICLE), namely when LO_VEHICLE contains bus or sports car references. That is the reason why with this kind of cast, the runtime system checks before the assignment whether the current content of the source variable corresponds to the type requirements of the target variable. Otherwise, an exception that can be handled is triggered and the original value of the target variable remains the same. You can identify this exception of the error class CX_SY_MOVE_CAST_ERROR using the TRYENDTRY and the CATCH statement. Another way of preventing this runtime error is to use runtime type identification (RTTI) classes. You can use RTTI classes to determine the dynamic type at runtime and set a condition for the cast.
146
© Copyright. All rights reserved.
Unit 3 Exercise 10 Implement Downcasts
Business Example As a developer, design an application where you want to determine the highest cargo load of all the cargo planes without knowing the details. Template: SAPBC401_INH_S3 Solution: SAPBC401_INH_S3_OPT Determine the highest cargo value. 1. In the LCL_CARGO_PLANE class, define and implement the GET_CARGO public functional method to return the cargo value. Define a returning parameter RV_CARGO. 2. In the LCL_CARRIER class, define and implement the GET_MAX_CARGO private function method to calculate the highest cargo value (load capacity) of all cargo planes. Loop at the list of airplanes and use the down-cast technique to identify cargo planes. For those airplanes for which the down-cast was successful, you can then call the GET_CARGO method defined and implemented in the previous step. 3. Call the GET_MAX_CARGO method from within the DISPLAY_ATTRIBUTES method class LCL_CARRIER and output the result.
© Copyright. All rights reserved.
147
Unit 3 Solution 10 Implement Downcasts
Business Example As a developer, design an application where you want to determine the highest cargo load of all the cargo planes without knowing the details. Template: SAPBC401_INH_S3 Solution: SAPBC401_INH_S3_OPT Determine the highest cargo value. 1. In the LCL_CARGO_PLANE class, define and implement the GET_CARGO public functional method to return the cargo value. Define a returning parameter RV_CARGO. a) See the source code extract from the model solution. 2. In the LCL_CARRIER class, define and implement the GET_MAX_CARGO private function method to calculate the highest cargo value (load capacity) of all cargo planes. Loop at the list of airplanes and use the down-cast technique to identify cargo planes. For those airplanes for which the down-cast was successful, you can then call the GET_CARGO method defined and implemented in the previous step. a) See the source code extract from the model solution. 3. Call the GET_MAX_CARGO method from within the DISPLAY_ATTRIBUTES method class LCL_CARRIER and output the result. a) See the source code extract from the model solution. SAPBC401_INH_S3_OPT REPORT
sapbc401_inh_s3_opt.
TYPE-POOLS icon. ... *---------------------------------------------------* * CLASS lcl_cargo_plane DEFINITION *---------------------------------------------------* CLASS lcl_cargo_plane DEFINITION INHERITING FROM lcl_airplane. PUBLIC SECTION. METHODS: constructor
148
© Copyright. All rights reserved.
Lesson: Implementing Downcasts Using Inheritance
IMPORTING iv_name TYPE string iv_planetype TYPE saplane-planetype iv_cargo TYPE s_plan_car EXCEPTIONS wrong_planetype, display_attributes REDEFINITION, get_cargo RETURNING value(rv_cargo) TYPE s_plan_car. PRIVATE SECTION. DATA: mv_cargo TYPE s_plan_car. ENDCLASS.
"lcl_cargo_plane DEFINITION
*----------------------------------------------------* * CLASS lcl_cargo_plane IMPLEMENTATION *----------------------------------------------------* CLASS lcl_cargo_plane IMPLEMENTATION. METHOD constructor. super->constructor( EXPORTING iv_name = iv_name iv_planetype = iv_planetype EXCEPTIONS wrong_planetype = 1 ). IF sy-subrc <> 0. RAISE wrong_planetype. ENDIF. mv_cargo = iv_cargo. ENDMETHOD. "constructor METHOD display_attributes. super->display_attributes( ). WRITE: / 'Max Cargo:'(005), AT c_pos_1 mv_cargo LEFT-JUSTIFIED. ULINE. ENDMETHOD. "display_attributes METHOD get_cargo. rv_cargo = mv_cargo. ENDMETHOD. ENDCLASS.
"get_cargo
"lcl_cargo_plane IMPLEMENTATION
... *---------------------------------------------------* * CLASS lcl_carrier DEFINITION *---------------------------------------------------* CLASS lcl_carrier DEFINITION. PUBLIC SECTION. METHODS: constructor IMPORTING iv_name TYPE string, display_attributes,
© Copyright. All rights reserved.
149
Unit 3: Inheritance and Casting
add_airplane IMPORTING io_plane TYPE REF TO lcl_airplane. PRIVATE SECTION. DATA: mv_name TYPE string, mt_airplanes TYPE TABLE OF REF TO lcl_airplane. METHODS: display_airplanes, get_max_cargo RETURNING value(rv_max_cargo) TYPE s_plan_car. ENDCLASS.
"lcl_carrier DEFINITION
*--------------------------------------------------* * CLASS lcl_carrier IMPLEMENTATION *--------------------------------------------------* CLASS lcl_carrier IMPLEMENTATION. METHOD constructor. mv_name = iv_name. ENDMETHOD.
"constructor
METHOD display_attributes. DATA: lv_max_cargo TYPE s_plan_car. SKIP 2. WRITE: icon_flight AS ICON, mv_name. ULINE. ULINE. me->display_airplanes( ). lv_max_cargo = me->get_max_cargo( ). WRITE: / 'Capacity of biggest cargo plane:'(max), lv_max_cargo LEFT-JUSTIFIED. ENDMETHOD.
"display_attributes
METHOD add_airplane. APPEND io_plane TO mt_airplanes. ENDMETHOD. "add_airplane METHOD display_airplanes. DATA: lo_plane TYPE REF TO lcl_airplane. LOOP AT mt_airplanes INTO lo_plane. lo_plane->display_attributes( ). ENDLOOP. ENDMETHOD. "display_airplanes METHOD get_max_cargo. DATA: lo_plane TYPE REF TO lcl_airplane, lo_cargo TYPE REF TO lcl_cargo_plane. LOOP AT mt_airplanes INTO lo_plane. TRY. lo_cargo ?= lo_plane.
150
© Copyright. All rights reserved.
Lesson: Implementing Downcasts Using Inheritance
IF rv_max_cargo < lo_cargo->get_cargo( ). rv_max_cargo = lo_cargo->get_cargo( ). ENDIF. *
CATCH cx_sy_move_cast_error. plane is not a cargo plane - do nothing ENDTRY. ENDLOOP. ENDMETHOD. "get_max_cargo
ENDCLASS.
© Copyright. All rights reserved.
"lcl_carrier IMPLEMENTATION
151
Unit 3: Inheritance and Casting
Usage of Class Hierarchies
Figure 80: Usage of Class Hierarchies
As early as the modeling phase, you can identify a generalization and specialization relationship between certain classes. If such a relationship exists between certain classes, you can use inheritance to represent this in ABAP Objects. For example, the semantics must be preserved when you redefine methods. Furthermore, inherited components must be used as intended in the superclass. Misuse of Inheritance
Figure 81: Examples – Misuse of Inheritance
If you do not have a correct understanding of the semantics of “is a (specific)”, you run the risk of identifying the wrong places in which to use inheritance. Sometimes the need for another attribute for a class is incorrectly answered with a specialization. For example, a superclass called Car, contains the subclasses red Car, blue Car, and so on. The statement “A red car is a specific car” is correct only at first glance. However, there are no cars without a color. At most, there are some cars that have not been painted. Therefore, every car needs the attribute color, assuming that it is relevant to the application. Therefore, that attribute must be defined in the superclass. There may be contradictions with reality when you try to implement a method for painting the cars.
152
© Copyright. All rights reserved.
Lesson: Implementing Downcasts Using Inheritance
Note: Such attributes are also defined as reference variables to a superclass of role classes. There is one description class for each role. To change the role of an instance, you then exchange the references to the corresponding role description instances. Specialist literature also refers to this as a role design pattern. In some cases, specialization relationships that do not allow for semantics to be retained need to be identified. For example, the square class inherits from the rectangle class. If you try to define methods for the rectangle that change the width and height separately, these methods will not make sense when applied to the square. Even if the methods are redefined to make the lengths of the sides uniform, the semantics will be different. For the same reason, that is, using inheritance only because some required functions are found in a superclass is also not appropriate.
© Copyright. All rights reserved.
153
Unit 3: Inheritance and Casting
LESSON SUMMARY You should now be able to:
154
●
Implement downcasts using inheritance
●
Model class hierarchies
© Copyright. All rights reserved.
Unit 3 Learning Assessment
1. Which of the following are the characteristics of inheritance? Choose the correct answers. X
A Common components only exist once in the superclass
X
B Components in the subclasses are available in all superclasses
X
C Subclasses contain extensions or changes
X
D Subclasses are not dependent on superclasses
2. A superclass is a generalization of its subclasses. Determine whether this statement is true or false. X
True
X
False
3. Suppose that you have a class X that inherits from class Y. After an up-cast a reference variable that is statically typed TYPE REF TO Y points to an instance of class X. What components of class X can you access with this reference variable? Choose the correct answers. X
A Components defined in class X
X
B Components inherited from class Y
X
C Components redefined in class X
X
D Components defined in class X and redefined in its subclasses
© Copyright. All rights reserved.
155
Unit 3: Learning Assessment
4. When objects from different classes react differently to the same method calls, this is known as __________. Choose the correct answer. X
A objects
X
B events
X
C polymorphism
X
D inheritance
5. A typical use for ________ assignments is to prepare for generic access. Choose the correct answer. X
A events
X
B upcast
X
C methods
X
D downcast
6. Which of the following is used to assign a superclass reference to a subclass reference? Choose the correct answer. X
A Widening Cast
X
B Narrowing Cast
X
C Redefinition
7. Which of the following is the down-cast assignment operator? Choose the correct answer.
156
X
A =
X
B <>
X
C ?=
X
D =?
© Copyright. All rights reserved.
Unit 3: Learning Assessment
8. Suppose you have the same class X that inherits from class Y. After a down-cast, a reference variable that is statically typed TYPE REF TO X points to an instance of class X. Which of the following components of class X can you access with this reference variable? Choose the correct answers. X
A Components defined in class X
X
B Components inherited from class Y
X
C Components redefined in class X
X
D Components defined in class X and redefined in its subclasses
X
E Components inherited and redefined from a ‘Friend’ relationship
9. Suppose a reference variable that is typed to an interface contains an instance reference of a class that implements this interface and you copy this to a reference variable that is typed to the class (down-cast). Which of the following components can you access with this reference variable? Choose the correct answers. X
A The components of the interface
X
B The components from the class that are not defined on the interface
X
C All components of the class
X
D The components of the interface for which alias names have been defined
X
E Components from a ‘Friend’ relationship
10. What are the advantages of correctly using class hierarchies? Choose the correct answers. X
A Centralized maintenance
X
B Safe and generic method of access
X
C Semantics preserved
X
D Intended use of inherited components
© Copyright. All rights reserved.
157
Unit 3 Learning Assessment - Answers
1. Which of the following are the characteristics of inheritance? Choose the correct answers. X
A Common components only exist once in the superclass
X
B Components in the subclasses are available in all superclasses
X
C Subclasses contain extensions or changes
X
D Subclasses are not dependent on superclasses
2. A superclass is a generalization of its subclasses. Determine whether this statement is true or false. X
True
X
False
3. Suppose that you have a class X that inherits from class Y. After an up-cast a reference variable that is statically typed TYPE REF TO Y points to an instance of class X. What components of class X can you access with this reference variable? Choose the correct answers.
158
X
A Components defined in class X
X
B Components inherited from class Y
X
C Components redefined in class X
X
D Components defined in class X and redefined in its subclasses
© Copyright. All rights reserved.
Unit 3: Learning Assessment - Answers
4. When objects from different classes react differently to the same method calls, this is known as __________. Choose the correct answer. X
A objects
X
B events
X
C polymorphism
X
D inheritance
5. A typical use for ________ assignments is to prepare for generic access. Choose the correct answer. X
A events
X
B upcast
X
C methods
X
D downcast
6. Which of the following is used to assign a superclass reference to a subclass reference? Choose the correct answer. X
A Widening Cast
X
B Narrowing Cast
X
C Redefinition
7. Which of the following is the down-cast assignment operator? Choose the correct answer. X
A =
X
B <>
X
C ?=
X
D =?
© Copyright. All rights reserved.
159
Unit 3: Learning Assessment - Answers
8. Suppose you have the same class X that inherits from class Y. After a down-cast, a reference variable that is statically typed TYPE REF TO X points to an instance of class X. Which of the following components of class X can you access with this reference variable? Choose the correct answers. X
A Components defined in class X
X
B Components inherited from class Y
X
C Components redefined in class X
X
D Components defined in class X and redefined in its subclasses
X
E Components inherited and redefined from a ‘Friend’ relationship
9. Suppose a reference variable that is typed to an interface contains an instance reference of a class that implements this interface and you copy this to a reference variable that is typed to the class (down-cast). Which of the following components can you access with this reference variable? Choose the correct answers. X
A The components of the interface
X
B The components from the class that are not defined on the interface
X
C All components of the class
X
D The components of the interface for which alias names have been defined
X
E Components from a ‘Friend’ relationship
10. What are the advantages of correctly using class hierarchies? Choose the correct answers.
160
X
A Centralized maintenance
X
B Safe and generic method of access
X
C Semantics preserved
X
D Intended use of inherited components
© Copyright. All rights reserved.
UNIT 4
Interfaces and Casting
Lesson 1 Defining and Implementing Local Interfaces Exercise 11: Define and Implement a Local Interface
162 167
Lesson 2 Implementing Polymorphism Using Interfaces Exercise 12: Implement Polymorphism Using Interfaces
177 181
Lesson 3 Integrating Class Models Using Interfaces Exercise 13: Integrate Class Models Using Interfaces
188 191
UNIT OBJECTIVES ●
Explain the use of interfaces
●
Create generalization and specialization relationships using interfaces
●
Implement polymorphism using interfaces
●
Implement downcasts with interfaces
●
Integrate different submodels using interfaces
●
Create and use interface hierarchies
© Copyright. All rights reserved.
161
Unit 4 Lesson 1 Defining and Implementing Local Interfaces
LESSON OVERVIEW This lesson explains the method of defining and implementing interfaces. Business Example As a developer, you need to create interfaces and implement them in your model in ABAP objects. For this reason, you require the following knowledge: ●
An understanding of interface use
●
An understanding of interface definition
●
An understanding of interface implementation
LESSON OBJECTIVES After completing this lesson, you will be able to: ●
Explain the use of interfaces
●
Create generalization and specialization relationships using interfaces
Use of Interfaces
Figure 82: Central Definition of Shared Components
Interfaces differ from regular inheritance in their areas of use. However, in terms of programming, there are hardly any differences between interfaces and regular inheritance. Interfaces can be seen as superclasses that cannot be instantiated, do not contain
162
© Copyright. All rights reserved.
Lesson: Defining and Implementing Local Interfaces
implementations, and have only public components. You can simulate multiple inheritances using interfaces. In ABAP Objects, interfaces primarily serve to define uniform interface protocols for services. Various classes can implement these services in different ways, but you need to keep the same semantics. Therefore, interfaces contain no implementations. In ABAP Objects, the same components can generally be defined in interfaces and classes. To recognize the semantic differences from regular inheritance, you can concentrate on the following use cases. For example, you want to allow multiple classes to implement a service in different ways, but using the same method names and a uniform signature. With regular inheritance, you would define such a method in the shared superclass. However, if you cannot model a superclass for inheritance suitably, you need to define an interface and then define the method in the interface. Therefore, you can compare this case with a generalization relationship within a superclass.
Definition of interfaces
Figure 83: Client Defines The Protocoll
Compared to regular inheritance, the distribution of roles in interfaces is sometimes different. The user generally defines the interfaces. In these interfaces, the user describes both technically and semantically the services that the user wants the providers to offer. Each class can now decide for itself whether it serves the interface, that is, whether it actually offers the services defined in the interface. Therefore, this case is similar to a specialization relationship with a subclass. As with regular inheritance, access to these services defined in the interface is then usually generic, that is, access to the services uses a reference that is typed on the interface. As in inheritance, polymorphism can also be implemented in interfaces.
© Copyright. All rights reserved.
163
Unit 4: Interfaces and Casting
Generic Access to Interface Components
Figure 84: Interfaces in UML Notation
In UML, you represent the interfaces in the same way as you represent classes. However, in addition to the interface’s name, you use notation «interface». You represent the use of an interface by a dotted line with a two-sided arrow from the user to the interface. The keyword «uses» is optional.
Generalization and Specialization Relationships Using Interfaces
Figure 85: Defining and Implementing an Interface
In ABAP Objects, you can define the same components in an interface as you can in classes. However, interfaces do not know the visibility levels of their components, that is, all the components of an interface are public. Classes implement interfaces in the following ways:
164
© Copyright. All rights reserved.
Lesson: Defining and Implementing Local Interfaces
●
Interface name The interface name is listed in the definition part of the class with the INTERFACES statement. This occurs in the PUBLIC SECTION, that is, interfaces can only be implemented publicly.
●
Interface methods The interface methods are implemented in the implementation part of the class.
●
Interface components The components defined in the interface are addressed in the implementation part of the class.
Interface components are distinguished from the other components in the implementing class by prefixing the interface name followed by a tilde (~), which is the interface resolution operator. interface_name~component_name To simplify access to interface components, you can use alias names. These alias names can appear in the definition part of a class or in the interface definition. The use of alias names is subject to the visibility restriction of the defining class. An alias for an interface method is defined as follows: ALIASES a_1 FOR lif_1~method_1. The interface method lif_1~method_1 can be addressed with the shorter form ref->a_1.
Access to Interface Components
Figure 86: Addressing Interface Components Using Object References
You can access interface components only by using an object reference whose class implements the interface. You use the interface resolution operator (~) to access the interface components in the implementation part of the class. Alternatively, you can use the alias names defined in the implementing class for the interface components. Even if shared components of the implementing classes are subsequently transferred to the interface, access to these components does not need to be adapted.
© Copyright. All rights reserved.
165
Unit 4: Interfaces and Casting
166
© Copyright. All rights reserved.
Unit 4 Exercise 11 Define and Implement a Local Interface
Business Example You need to add a car rental company to your program. The car rental company together with the existing airline needs to be added into the travel agency class as the travel agency’s business partners. To add these business partners, you need a generic access to airlines and car rental companies. Instead of defining a common superclass, you need to define an interface with generic services, which is then implemented in the classes for airlines and car rental companies. Define and implement the interface in your existing class for airlines. Template: SAPBC401_INH_S3 Solution: SAPBC401_INT_S1 Create an INCLUDE Program from the Main Program To increase the legibility of your program, split the source code into a main program and one INCLUDE program. The INCLUDE program must contain all the local class definitions and implementations. The declaration of reference variables and the START-OF-SELECTION event block should remain in the main program.
Note: This distribution does not follow the recommended use of INCLUDES in ABAP programs. According to the programming guidelines, the class definitions and data declarations should go to the TOP-INCLUDE, the implementations to a PINCLUDE, and the START-OF-SELECTION event block to an E-INCLUDE. 1. Complete your program ZBC401_##_MAIN (## is your two-digit group number) or copy the sample solution from the previous exercise. 2. In your main program, implement the usage of a new INCLUDE program (recommended name: ZBC401_##_CARRIER with ## being your two-digit group number). Create the INCLUDE through forward navigation. You can do this by double-clicking the name of the INCLUDE. 3. Cut the definition and implementation sections of all four local classes from the main program and paste them on to the newly created include program.
© Copyright. All rights reserved.
167
Unit 4: Interfaces and Casting
4. Where do you have to place the INCLUDE statement to avoid syntax errors?
5. Activate and test your program.
Define an Interface Define an interface with the DISPLAY_PARTNER method in order to later offer generic access options to potential clients in the travel agency example. 1. Create a new INCLUDE (recommended name: ZBC401_##_AGENCY with ## being your two-digit group number) and define an interface LIF_PARTNER in the new INCLUDE. 2. The interface should contain the DISPLAY_PARTNER instance method. The instance method should not have any parameters. Later , your task will be to display business partner attributes. Check the entire program for syntactical correctness and activate it. Implement an Interface The LCL_CARRIER class should make the services defined in the interface available to potential clients. To achieve this, class LCL_CARRIER needs to implement the interface and therefore the interface method DISPLAY_PARTNER. 1. In the definition of LCL_CARRIER, declare the newly created interface. 2. Implement the coding of the DISPLAY_PARTNER interface method in the LCL_CARRIER class. As is evident from the name of the method, the data or attributes of this business partner should be displayed here. Consider the possible solutions and execute the most suitable approach. Check the entire application for syntactical correctness and activate your application. Hint: The performance of the application will still not change at this point; the results can be seen only in the later tasks.
Test the Interface Test the interface implemented in the LCL_CARRIER class by calling the interface method from the main program. 1. In the main program, remove the call for the DISPLAY_ATTRIBUTES method of the LCL_CARRIER class. Replace it with a call for the DISPLAY_PARTNER interface method.
168
© Copyright. All rights reserved.
Lesson: Defining and Implementing Local Interfaces
2. What would be the objective of such a call at this point of the exercise be, or in other words, what does the option of this interface method call bring out of the main program in contrast with a conventional method call?
3. After a successful test, turn this method call into a comment so that it becomes ineffective. Hint: The generic use of the interface methods with another class takes place in the next steps of the exercise. The performance of the entire application will still not change at this point; the results can be seen only in later tasks.
© Copyright. All rights reserved.
169
Unit 4 Solution 11 Define and Implement a Local Interface
Business Example You need to add a car rental company to your program. The car rental company together with the existing airline needs to be added into the travel agency class as the travel agency’s business partners. To add these business partners, you need a generic access to airlines and car rental companies. Instead of defining a common superclass, you need to define an interface with generic services, which is then implemented in the classes for airlines and car rental companies. Define and implement the interface in your existing class for airlines. Template: SAPBC401_INH_S3 Solution: SAPBC401_INT_S1 Create an INCLUDE Program from the Main Program To increase the legibility of your program, split the source code into a main program and one INCLUDE program. The INCLUDE program must contain all the local class definitions and implementations. The declaration of reference variables and the START-OF-SELECTION event block should remain in the main program.
Note: This distribution does not follow the recommended use of INCLUDES in ABAP programs. According to the programming guidelines, the class definitions and data declarations should go to the TOP-INCLUDE, the implementations to a PINCLUDE, and the START-OF-SELECTION event block to an E-INCLUDE. 1. Complete your program ZBC401_##_MAIN (## is your two-digit group number) or copy the sample solution from the previous exercise. a) Carry out this step in the usual manner. Additional information about the copying of programs is available in the SAP Library. 2. In your main program, implement the usage of a new INCLUDE program (recommended name: ZBC401_##_CARRIER with ## being your two-digit group number). Create the INCLUDE through forward navigation. You can do this by double-clicking the name of the INCLUDE. a) See the source text excerpt from the model solution. 3. Cut the definition and implementation sections of all four local classes from the main program and paste them on to the newly created include program.
170
© Copyright. All rights reserved.
Lesson: Defining and Implementing Local Interfaces
a) See the source text excerpt from the model solution. 4. Where do you have to place the INCLUDE statement to avoid syntax errors? The INCLUDE statement has to be placed before the declaration of reference variables. Otherwise, the class definitions are not known in the declaration of reference variables. 5. Activate and test your program. a) Carry out this step in the usual manner. Additional information about the copying of programs is available in the SAP Library.
Define an Interface Define an interface with the DISPLAY_PARTNER method in order to later offer generic access options to potential clients in the travel agency example. 1. Create a new INCLUDE (recommended name: ZBC401_##_AGENCY with ## being your two-digit group number) and define an interface LIF_PARTNER in the new INCLUDE. a) See the source text excerpt from the model solution. 2. The interface should contain the DISPLAY_PARTNER instance method. The instance method should not have any parameters. Later , your task will be to display business partner attributes. Check the entire program for syntactical correctness and activate it. a) See the source text excerpt from the model solution. Implement an Interface The LCL_CARRIER class should make the services defined in the interface available to potential clients. To achieve this, class LCL_CARRIER needs to implement the interface and therefore the interface method DISPLAY_PARTNER. 1. In the definition of LCL_CARRIER, declare the newly created interface. a) See the source text excerpt from the model solution. 2. Implement the coding of the DISPLAY_PARTNER interface method in the LCL_CARRIER class. As is evident from the name of the method, the data or attributes of this business partner should be displayed here. Consider the possible solutions and execute the most suitable approach. Check the entire application for syntactical correctness and activate your application. Hint: The performance of the application will still not change at this point; the results can be seen only in the later tasks. a) See the source text excerpt from the model solution. Test the Interface Test the interface implemented in the LCL_CARRIER class by calling the interface method from the main program.
© Copyright. All rights reserved.
171
Unit 4: Interfaces and Casting
1. In the main program, remove the call for the DISPLAY_ATTRIBUTES method of the LCL_CARRIER class. Replace it with a call for the DISPLAY_PARTNER interface method. a) See the source text excerpt from the model solution. 2. What would be the objective of such a call at this point of the exercise be, or in other words, what does the option of this interface method call bring out of the main program in contrast with a conventional method call? Apart from the detailed and longer syntax of this call, the call of the interface method can be replaced by an ordinary instance method call from, for example, DISPLAY_ATTRIBUTES. At this point in the exercise, this call does not seem altogether sensible. 3. After a successful test, turn this method call into a comment so that it becomes ineffective. Hint: The generic use of the interface methods with another class takes place in the next steps of the exercise. The performance of the entire application will still not change at this point; the results can be seen only in later tasks. a) See the source text excerpt from the model solution. Main program: SAPBC401_INT_S1 REPORT
sapbc401_int_s1.
TYPE-POOLS icon. INCLUDE bc401_int_s1_agency. INCLUDE bc401_int_s1_carrier. DATA: go_carrier go_airplane go_cargo go_passenger gv_count
TYPE TYPE TYPE TYPE TYPE
REF REF REF REF i.
TO TO TO TO
lcl_carrier, lcl_airplane, lcl_cargo_plane, lcl_passenger_plane,
START-OF-SELECTION. ******************* ***** Create Carrier ************************************ CREATE OBJECT go_carrier EXPORTING iv_name = 'Smile&Fly-Travel'. ***** Passenger Plane CREATE OBJECT go_passenger EXPORTING iv_name = 'LH BERLIN' iv_planetype = '747-400' iv_seats = 345 EXCEPTIONS wrong_planetype = 1.
172
© Copyright. All rights reserved.
Lesson: Defining and Implementing Local Interfaces
IF sy-subrc = 0. go_carrier->add_airplane( go_passenger ). ENDIF. ***** cargo Plane CREATE OBJECT go_cargo EXPORTING iv_name = 'US Hercules' iv_planetype = '747-200F' iv_cargo = 533 EXCEPTIONS wrong_planetype = 1. IF sy-subrc = 0. go_carrier->add_airplane( go_cargo ). ENDIF. *** output carrier (including list of airplanes) * only for testing: * call interface method for the carrier *
go_carrier->lif_partner~display_partner( ). go_carrier->display_attributes( ). Include BC401_INT_S1_AGENCY
INTERFACE lif_partner. METHODS display_partner. ENDINTERFACE. Include BC401_INT_S1_CARRIER *---------------------------------------------------* * CLASS lcl_airplane DEFINITION *---------------------------------------------------* CLASS lcl_airplane DEFINITION. ... ENDCLASS. "lcl_airplane DEFINITION *---------------------------------------------------* * CLASS lcl_airplane IMPLEMENTATION *---------------------------------------------------* CLASS lcl_airplane IMPLEMENTATION. ... ENDCLASS. "lcl_airplane IMPLEMENTATION *----------------------------------------------------* * CLASS lcl_cargo_plane DEFINITION *----------------------------------------------------* * *----------------------------------------------------* CLASS lcl_cargo_plane DEFINITION INHERITING FROM lcl_airplane. ... ENDCLASS. "lcl_cargo_plane DEFINITION *--------------------------------------------------* * CLASS lcl_cargo_plane IMPLEMENTATION
© Copyright. All rights reserved.
173
Unit 4: Interfaces and Casting
*--------------------------------------------------* CLASS lcl_cargo_plane IMPLEMENTATION. ... ENDCLASS. "lcl_cargo_plane IMPLEMENTATION *--------------------------------------------------* * CLASS lcl_passenger_plane DEFINITION *--------------------------------------------------* CLASS lcl_passenger_plane DEFINITION INHERITING FROM lcl_airplane. ... ENDCLASS. "lcl_passenger_plane DEFINITION *---------------------------------------------------* * CLASS lcl_passenger_plane IMPLEMENTATION *---------------------------------------------------* CLASS lcl_passenger_plane IMPLEMENTATION. ... ENDCLASS.
"lcl_passenger_plane IMPLEMENTATION
*----------------------------------------------------* * CLASS lcl_carrier DEFINITION *----------------------------------------------------* CLASS lcl_carrier DEFINITION. PUBLIC SECTION. INTERFACES: lif_partner. METHODS: constructor IMPORTING iv_name TYPE string, display_attributes, add_airplane IMPORTING io_plane TYPE REF TO lcl_airplane. PRIVATE SECTION. DATA: mv_name TYPE string, mt_airplanes TYPE TABLE OF REF TO lcl_airplane. METHODS: display_airplanes. ENDCLASS.
"lcl_carrier DEFINITION
*---------------------------------------------------* * CLASS lcl_carrier IMPLEMENTATION *---------------------------------------------------* CLASS lcl_carrier IMPLEMENTATION. METHOD constructor. mv_name = iv_name. ENDMETHOD. "constructor METHOD display_attributes.
174
© Copyright. All rights reserved.
Lesson: Defining and Implementing Local Interfaces
SKIP 2. WRITE: icon_flight AS ICON, mv_name. ULINE. ULINE. me->display_airplanes( ). ENDMETHOD. "display_attributes METHOD add_airplane. APPEND io_plane TO mt_airplanes. ENDMETHOD. "add_airplane METHOD display_airplanes. DATA: lo_plane TYPE REF TO lcl_airplane. LOOP AT mt_airplanes INTO lo_plane. lo_plane->display_attributes( ). ENDLOOP. ENDMETHOD. "display_airplanes METHOD lif_partner~display_partner. me->display_attributes( ). ENDMETHOD. "lif_partner~display_partner ENDCLASS.
© Copyright. All rights reserved.
"lcl_carrier IMPLEMENTATION
175
Unit 4: Interfaces and Casting
LESSON SUMMARY You should now be able to:
176
●
Explain the use of interfaces
●
Create generalization and specialization relationships using interfaces
© Copyright. All rights reserved.
Unit 4 Lesson 2 Implementing Polymorphism Using Interfaces
LESSON OVERVIEW This lesson explains polymorphism and implementing polymorphism using interfaces. Business Example As a developer, you need to create interfaces and implement polymorphism in your ABAP Objects project. For this reason, you require the following knowledge: ●
An understanding of polymorphism
●
An understanding of polymorphism in interface implementation
LESSON OBJECTIVES After completing this lesson, you will be able to: ●
Implement polymorphism using interfaces
Polymorphism with Interfaces
Figure 87: Up-Cast with Interface References
An interface reference can only refer to instances of classes that have implemented the interface because interfaces themselves cannot be instantiated. As in regular inheritance, you must use up-cast to copy a reference to the interface reference variable to perform polymorphism with interfaces. If the class has implemented the interface, it is certain that all the components that can be accessed syntactically after the cast assignment are available in the instance. A user can
© Copyright. All rights reserved.
177
Unit 4: Interfaces and Casting
address the instance of the implementing class using the interface. The prefixing of the interface name and the interface resolution operator is omitted. However, the user is restricted to using the components from the interface. In the example, the DISPLAY_PARTNER and CHECK_AVAILABILITY methods of the LIF_PARTNER interface can be accessed only after assigning the reference variable GO_PARTNER. It is not possible to access the specific components of the instance from the LCL_RENTAL (GET_NAME in the above example) class using the GO_PARTNER reference variable. Therefore, the view is narrowed or, at least, remains unchanged. That is why you describe this type of assignment of reference variables as up-cast. There is a switch from a view of several components to a view of only a few components. The target reference can, of course, accept more dynamic types after the assignment, than it could before. Therefore, the term widening cast is also suitable.
Generic Access with Interfaces
Figure 88: Row Type of the Internal Table in the Application Example
A typical area of use for up-cast assignments is preparation for generic access. A user who is not interested in the finer points of the instances of the class that implement the interface but who simply wants to address the components defined in the interface, could use an interface reference for this access. In the example shown, a travel agency (LCL_TRAVEL_AGENCY) needs to manage the various kinds of business partners in one list. The developer must therefore assign the row type of the internal table as the reference to the interface LIF_PARTNER. The travel agency only wants to request the services in order to display their attributes and check their availability. The relevant DISPLAY_PARTNER and CHECK_AVAILABILITY methods are defined in the LIF_PARTNER interface and implemented in all business partner classes. The objects of different classes (LCL_HOTEL, LCL_RENTAL, and LCL_CARRIER in the example) can be kept in an internal table, typed with interface references (LIF_PARTNER in the example). The components defined in the interface can then be accessed uniformly. For this example, the ADD_PARTNER method is needed. This method copies the references to all kinds of business partners in the internal table. The import parameter of this method is already typed as the reference to the interface.
178
© Copyright. All rights reserved.
Lesson: Implementing Polymorphism Using Interfaces
Generic Access Using the Interface Reference
Figure 89: Polymorphism – Generic Access Using the Interface Reference
Polymorphism can also be performed for interfaces. You can use interface references to call methods and execute different implementations depending on the object of the reference. The dynamic type of the reference variable is used to search for the implementation of a method. In the above example, lo_partner->display_partner( ) uses the class of the instance to which lo_partner actually refers in order to search for the implementation of display_partner. The implementation that is executed when DISPLAY_PARTNER is called now depends on the object to which the interface reference lo_partner currently refers. When objects from different classes react differently to the same method calls, it is known as polymorphism. The option of performing polymorphism is one of the main strengths of interfaces. A client can handle different classes uniformly, regardless of their implementation. The runtime system searches for the right implementation of a method on behalf of the client. Polymorphism can be used to write programs that are highly generic, that is, they do not need to be changed significantly if use cases are added. In the example, it becomes easy to add a class for boat rentals. For example, the relevant class with the name LCL_SHIPPING will simply have to implement the LIF_PARTNER interface and the DISPLAY_PARTNER method defined there. Business partner management can then easily include ship-owning companies and request them to display their attributes.
© Copyright. All rights reserved.
179
Unit 4: Interfaces and Casting
180
© Copyright. All rights reserved.
Unit 4 Exercise 12 Implement Polymorphism Using Interfaces
Business Example You need to add a class that uses the previously defined interface. Travel agencies need to manage various business partners using the interface and access general services of the business partners. Template: SAPBC401_INH_T2 Solution: SAPBC401_INT_S2 Define a Local Class Define a local class for travel agencies. 1. Complete your program ZBC401_##_MAIN (## is your two-digit group number) or copy the template program with all its INCLUDES. 2. In the INCLUDE program that contains the definition of the LIF_PARTNER interface, define and implement the LCL_TRAVEL_AGENCY local class. Hint: If you have not copied the template program, you can reduce your typing load by copying the definition and implementation of the LCL_TRAVEL_AGENCY class from the SAPBC401_INT_T2 template and include BC401_INT_T2_AGENCY. You can also create the LCL_TRAVEL_AGENCY class from scratch, without using templates. 3. As a private class attribute, add an internal table MT_PARTNERS for the buffering of references to the business partners who have implemented the LIF_PARTNER interface. 4. Define and implement a public method named ADD_PARTNER so that the business partner references can be added to the MT_PARTNERS list. Define an import parameter named IO_PARTNER with an appropriate type. 5. Extend the implementation of the DISPLAY_ATTRIBUTES method in a way that it not only displays information about the travel agency but also about its business partners. Use the previously defined DISPLAY_PARTNERS method.
Generate an Instance and Transfer References to the Instance In the main program, generate a travel agency instance, transfer the references to the airline to this instance, and add the attributes.
© Copyright. All rights reserved.
181
Unit 4: Interfaces and Casting
1. In the main program, define a suitably typed reference variable for your new travel agency class. 2. Using the reference, generate an instance of your class LCL_TRAVEL_AGENCY. Decide how to fill out the attributes. 3. Call the ADD_PARTNER method to transfer the references to the generated airline instances to the travel agency. 4. Display the attributes of the travel agency (including information about its business partners) by calling its method DISPLAY_ATTRIBUTES.
182
© Copyright. All rights reserved.
Unit 4 Solution 12 Implement Polymorphism Using Interfaces
Business Example You need to add a class that uses the previously defined interface. Travel agencies need to manage various business partners using the interface and access general services of the business partners. Template: SAPBC401_INH_T2 Solution: SAPBC401_INT_S2 Define a Local Class Define a local class for travel agencies. 1. Complete your program ZBC401_##_MAIN (## is your two-digit group number) or copy the template program with all its INCLUDES. a) Carry out this step in the usual manner. For more information, refer to the SAP Library. 2. In the INCLUDE program that contains the definition of the LIF_PARTNER interface, define and implement the LCL_TRAVEL_AGENCY local class. Hint: If you have not copied the template program, you can reduce your typing load by copying the definition and implementation of the LCL_TRAVEL_AGENCY class from the SAPBC401_INT_T2 template and include BC401_INT_T2_AGENCY. You can also create the LCL_TRAVEL_AGENCY class from scratch, without using templates. a) Carry out this step in the usual manner. For more information, refer to the SAP Library. 3. As a private class attribute, add an internal table MT_PARTNERS for the buffering of references to the business partners who have implemented the LIF_PARTNER interface. a) See the source text excerpt from the model solution. 4. Define and implement a public method named ADD_PARTNER so that the business partner references can be added to the MT_PARTNERS list. Define an import parameter named IO_PARTNER with an appropriate type. a) See the source text excerpt from the model solution. 5. Extend the implementation of the DISPLAY_ATTRIBUTES method in a way that it not only displays information about the travel agency but also about its business partners. Use the previously defined DISPLAY_PARTNERS method. a) See the source text excerpt from the model solution.
© Copyright. All rights reserved.
183
Unit 4: Interfaces and Casting
Generate an Instance and Transfer References to the Instance In the main program, generate a travel agency instance, transfer the references to the airline to this instance, and add the attributes. 1. In the main program, define a suitably typed reference variable for your new travel agency class. a) See the source text excerpt from the model solution. 2. Using the reference, generate an instance of your class LCL_TRAVEL_AGENCY. Decide how to fill out the attributes. a) See the source text excerpt from the model solution. 3. Call the ADD_PARTNER method to transfer the references to the generated airline instances to the travel agency. a) See the source text excerpt from the model solution. 4. Display the attributes of the travel agency (including information about its business partners) by calling its method DISPLAY_ATTRIBUTES. a) See the source text excerpt from the model solution. Include BC401_INT_S2_AGENCY *&-------------------------------------------------* *& Include BC401_INT_S2_AGENCY *&-------------------------------------------------* INTERFACE lif_partner. METHODS: display_partner. ENDINTERFACE. "lif_partner *--------------------------------------------------* * CLASS lcl_travel_agency DEFINITION *--------------------------------------------------* CLASS lcl_travel_agency DEFINITION. PUBLIC SECTION. METHODS: constructor IMPORTING iv_name TYPE string, add_partner IMPORTING io_partner TYPE REF TO lif_partner, display_agency_partners, display_attributes. PRIVATE SECTION. DATA: mv_name TYPE string, mt_partners TYPE TABLE OF REF TO lif_partner. ENDCLASS.
"lcl_travel_agency DEFINITION
*---------------------------------------------------* * CLASS lcl_travel_agency IMPLEMENTATION *---------------------------------------------------*
184
© Copyright. All rights reserved.
Lesson: Implementing Polymorphism Using Interfaces
CLASS lcl_travel_agency IMPLEMENTATION. METHOD display_attributes. WRITE: / icon_private_files AS ICON, 'Travel Agency:'(007), mv_name. ULINE. display_agency_partners( ). ENDMETHOD. "display_attributes METHOD display_agency_partners. DATA: lo_partner TYPE REF TO lif_partner. WRITE 'Here are the partners of the travel agency:'(008). ULINE. LOOP AT mt_partners INTO lo_partner. lo_partner->display_partner( ). ENDLOOP. ENDMETHOD.
"display_agency_partners
METHOD constructor. mv_name = iv_name. ENDMETHOD. "constructor METHOD add_partner. APPEND io_partner TO mt_partners. ENDMETHOD. "add_partner ENDCLASS.
"lcl_travel_agency IMPLEMENTATION
Main Program SAPBC401_INT_S2 REPORT
sapbc401_int_s2.
TYPE-POOLS icon. INCLUDE bc401_int_s2_agency. INCLUDE bc401_int_s2_carrier. DATA: go_agency go_carrier go_airplane go_cargo go_passenger gv_count
TYPE TYPE TYPE TYPE TYPE TYPE
REF REF REF REF REF i.
TO TO TO TO TO
lcl_travel_agency, lcl_carrier, lcl_airplane, lcl_cargo_plane, lcl_passenger_plane,
START-OF-SELECTION. ******************* ***** create travel_agency CREATE OBJECT go_agency EXPORTING iv_name = 'Travel&Smile Travel'. ***** Create Carrier CREATE OBJECT go_carrier EXPORTING iv_name = 'Smile&Fly Travel'.
© Copyright. All rights reserved.
185
Unit 4: Interfaces and Casting
***** Insert carrier into business partner list of ***** travel agency go_agency->add_partner( go_carrier ). ***** Passenger Plane CREATE OBJECT go_passenger EXPORTING iv_name = 'LH BERLIN' iv_planetype = '747-400' iv_seats = 345 EXCEPTIONS wrong_planetype = 1. IF sy-subrc = 0. go_carrier->add_airplane( go_passenger ). ENDIF. ***** cargo Plane CREATE OBJECT go_cargo EXPORTING iv_name = 'US Hercules' iv_planetype = '747-200F' iv_cargo = 533 EXCEPTIONS wrong_planetype = 1. IF sy-subrc = 0. go_carrier->add_airplane( go_cargo ). ENDIF. ***** show attributes of all partners of ***** travel agency go_agency->display_attributes( ).
186
© Copyright. All rights reserved.
Lesson: Implementing Polymorphism Using Interfaces
LESSON SUMMARY You should now be able to: ●
Implement polymorphism using interfaces
© Copyright. All rights reserved.
187
Unit 4 Lesson 3 Integrating Class Models Using Interfaces
LESSON OVERVIEW This lesson explains the method of joining classmodels using interfaces. Business Example As a developer, you need to integrate multiple class models of your ABAP Objects project. For this reason, you require the following knowledge: ●
An understanding of submodels
●
An understanding of integrating submodels
●
An understanding of interface hierarchies
LESSON OBJECTIVES After completing this lesson, you will be able to: ●
Implement downcasts with interfaces
●
Integrate different submodels using interfaces
●
Create and use interface hierarchies
Downcasts with Interfaces
Figure 90: Down-Cast Assignment and Exception Handling in the Application Example
To assign an interface reference to a class reference where the class has implemented the interface, you must use the down-cast assignment operator MOVE ... ?TO ... or its short
188
© Copyright. All rights reserved.
Lesson: Integrating Class Models Using Interfaces
form ?=. Otherwise, the system would return a message stating that it is not certain that all components that can be accessed syntactically after the cast assignment are actually available in the instance. As a rule, the implementing class contains more components than the interface. Interface reference variables can contain references to instances of the implementing class at runtime. After assigning this type of reference back to a reference to the implementing class, clients are no longer limited to interface components.
Submodel Integration Using Interfaces This type of reference variable assignment is described as down-casting. The down-casting view is widened or at least unchanged. This is a switch from a view of a few components to a view of more components. The term Narrowing Cast is also used. A typical area of use for down-cast assignments is when specific components of instances need to be addressed whose references are kept in variables that are typed on the interface. A user who is interested in the finer points of the instances in implementing classes cannot use the interface reference because the downcast assignment only allows access to the interface components. In the example shown in figure Down-Cast Assignment and Exception Handling in the Application Example, a travel agency (LCL_TRAVEL_AGENCY) needs to book a flight but keeps all the various business partner references in an internal table that was typed on the interface LIF_PARTNER. What happens if there is no airline reference in the interface reference GO_PARTNER at runtime, but the down-cast assignment operator is used to copy the reference to the theninvalid reference GO_CARRIER? In contrast to the up-cast assignment, it is possible that the static type of the target variable(GO_CARRIER) is neither more general than nor the same as the dynamic type of the source variables (GO_PARTNER), specifically if GO_PARTNER contains hotel or car rental references. The runtime system checks this type of cast before the assignment, whether or not the current content of the source variable corresponds to the type requirements of the target variable. Otherwise, an exception that can be handled is triggered, and the original value of the target variable remains the same. This exception of error class CX_SY_MOVE_CAST_ERROR can be identified using TRY-ENDTRY and the CATCH statement. Another way to prevent this runtime error would be to use runtime type identification (RTTI) classes. They can be used to determine the dynamic type at runtime and to set a condition for the cast. Assignments between interface reference variables, whose typing interfaces are not related to each other, cannot be checked statically and must therefore be performed using downcast. With such an assignment, the system checks at runtime whether the class of the instance to which the source reference refers also supports the interface with which the target reference is typed.
© Copyright. All rights reserved.
189
Unit 4: Interfaces and Casting
190
© Copyright. All rights reserved.
Unit 4 Exercise 13 Integrate Class Models Using Interfaces
Business Example You need to add the car rental company with its vehicles to your own object model. By implementing the already defined interface, you can ensure that the car rental company can be added to the list of business partners of the travel agency.
Note: This exercise uses the main program file ZBC401_##_MAIN completed in the previous exercise. If not completed, copy the model solution with all its INCLUDES from the previous exercise, then add the code from the template program and INCLUDE file for this program. . In the exercises for this course, when the input values include ##, replace ## with your group number. Templates SAPBC401_INT_S2 SAPBC401_INT_T3 BC401_INT_T3_RENTAL Solution SAPBC401_INT_S3 BC401_INT_S3_RENTAL Add the Vehicle Model to Your Application Copy the definitions and implementations of classes LCL_RENTAL and the vehicle classes (LCL_VEHICLE, LCL_TRUCK and LCL_BUS) to your program and create instances of these classes. 1. Copy the definitions and implementations of classes LCL_RENTAL and the vehicle classes (LCL_VEHICLE, LCL_TRUCK and LCL_BUS) to your program. 2. In your main program, add the reference pointers for LCL_RENTAL, LCL_VEHICLE, LCL_TRUCK AND LCL_BUS. Then create an instance of LCL_RENTAL and a number of instances of the truck and bus classes. Add all the vehicles to the rental company’s list of vehicles by calling method ADD_VEHICLE of LCL_RENTAL. Hint: To reduce the typing effort, you can copy and paste the relevant coding from the main program of SAPBC401_INT_T3. Implement the Business Partner Interface Implement interface LIF_PARTNER in class LCL_RENTAL.
© Copyright. All rights reserved.
191
Unit 4: Interfaces and Casting
1. Call method ADD_PARTNER to add the instance of LCL_RENTAL to the travel agency’s list of business partners. 2. Perform a syntax check. Why does this method call cause a syntax error?
3. Go to the definition part of class LCL_RENTAL and declare the implementation of interface LIF_PARTNER. 4. Implement the method DISPLAY_PARTNER of the interface LIF_PARTNER in the implementation section of class LCL_RENTAL. 5. Check, save, and activate the program and INCLUDE files. Then go to the main program and perform another syntax check 6. Run the program. Why does the call of ADD_PARTNER now work for the car rental company?
192
© Copyright. All rights reserved.
Unit 4 Solution 13 Integrate Class Models Using Interfaces
Business Example You need to add the car rental company with its vehicles to your own object model. By implementing the already defined interface, you can ensure that the car rental company can be added to the list of business partners of the travel agency.
Note: This exercise uses the main program file ZBC401_##_MAIN completed in the previous exercise. If not completed, copy the model solution with all its INCLUDES from the previous exercise, then add the code from the template program and INCLUDE file for this program. . In the exercises for this course, when the input values include ##, replace ## with your group number. Templates SAPBC401_INT_S2 SAPBC401_INT_T3 BC401_INT_T3_RENTAL Solution SAPBC401_INT_S3 BC401_INT_S3_RENTAL Add the Vehicle Model to Your Application Copy the definitions and implementations of classes LCL_RENTAL and the vehicle classes (LCL_VEHICLE, LCL_TRUCK and LCL_BUS) to your program and create instances of these classes. 1. Copy the definitions and implementations of classes LCL_RENTAL and the vehicle classes (LCL_VEHICLE, LCL_TRUCK and LCL_BUS) to your program. a) In the Object Navigator, in the unnamed dropdown list on the left of the screen, choose Package and enter BC401,, press Enter. b) In the Object Name screen area, expand the Includes node. c) On the list, right-click the entry BC401_INT_T3_RENTAL , choose Copy. The Copy Program ZBC401_##_RENTAL, dialog box displays. d) In the Copy Program ZBC401_##_RENTAL, dialog, in the Target Program field, enter ZBC401_##_RENTAL,. Choose Copy. The Create Object Directory Entry dialog box displays. e) In the Create Object Directory Entry dialog box, enter your package name and choose Save.
© Copyright. All rights reserved.
193
Unit 4: Interfaces and Casting
The Prompt for transportable Workbench request dialog box displays f) In the Prompt for transportable Workbench request dialog box, enter the request name supplied by your instructor. Choose Continue. 2. In your main program, add the reference pointers for LCL_RENTAL, LCL_VEHICLE, LCL_TRUCK AND LCL_BUS. Then create an instance of LCL_RENTAL and a number of instances of the truck and bus classes. Add all the vehicles to the rental company’s list of vehicles by calling method ADD_VEHICLE of LCL_RENTAL. Hint: To reduce the typing effort, you can copy and paste the relevant coding from the main program of SAPBC401_INT_T3. a) See the source text excerpt from the model solution. Implement the Business Partner Interface Implement interface LIF_PARTNER in class LCL_RENTAL. 1. Call method ADD_PARTNER to add the instance of LCL_RENTAL to the travel agency’s list of business partners. a) See the source text excerpt from the model solution. 2. Perform a syntax check. Why does this method call cause a syntax error? The upcast in the parameter passing of the method does not work because the types LCL_RENTAL and LIF_PARTNER are not compatible. They will become compatible as soon as LCL_RENTAL implements the interface. 3. Go to the definition part of class LCL_RENTAL and declare the implementation of interface LIF_PARTNER. a) See the source text excerpt from the model solution. 4. Implement the method DISPLAY_PARTNER of the interface LIF_PARTNER in the implementation section of class LCL_RENTAL. a) See the source text excerpt from the model solution. 5. Check, save, and activate the program and INCLUDE files. Then go to the main program and perform another syntax check a) Save your program. b) To check your program, on the application toolbar choose the Check button. c) To activate your program, on the application toolbar choose the Activate button. 6. Run the program.
194
© Copyright. All rights reserved.
Lesson: Integrating Class Models Using Interfaces
Why does the call of ADD_PARTNER now work for the car rental company? Because now the types LCL_RENTAL and LIF_PARTNER are compatible. LCL_RENTAL implements interface LIF_PARTNER. Any instance of LCL_RENTAL is accepted as a business partner. a) To run your program, on the application toolbar choose the Direct Processing button. Solution: Main Program SAPBC401_INT_S3 REPORT
sapbc401_int_s3.
TYPE-POOLS icon. INCLUDE bc401_int_s3_agency. INCLUDE bc401_int_s3_carrier. INCLUDE bc401_int_s3_rental. DATA: go_vehicle go_truck go_bus go_rental
TYPE TYPE TYPE TYPE
REF REF REF REF
TO TO TO TO
lcl_vehicle, lcl_truck, lcl_bus, lcl_rental.
DATA: go_agency go_carrier go_airplane go_cargo go_passenger gv_count
TYPE TYPE TYPE TYPE TYPE TYPE
REF REF REF REF REF i.
TO TO TO TO TO
lcl_travel_agency, lcl_carrier, lcl_airplane, lcl_cargo_plane, lcl_passenger_plane,
START-OF-SELECTION. ******************* ******* create travel_agency ********************************** CREATE OBJECT go_agency EXPORTING iv_name = 'Travel&Smile Travel'. ******* create rental ***************************************** CREATE OBJECT go_rental EXPORTING iv_name = 'Happy Car Rental'. ***** Insert rental company into partner list of travel agency go_agency->add_partner( go_rental ). ******* create truck ****************************************** CREATE OBJECT go_truck EXPORTING iv_make = 'MAN' iv_cargo = 45. go_rental->add_vehicle( go_truck ). ******* create truck ****************************************** CREATE OBJECT go_bus EXPORTING iv_make = 'Mercedes' iv_passengers = 80.
© Copyright. All rights reserved.
195
Unit 4: Interfaces and Casting
go_rental->add_vehicle( go_bus ). ******* create truck ****************************************** CREATE OBJECT go_truck EXPORTING iv_make = 'VOLVO' iv_cargo = 48. go_rental->add_vehicle( go_truck ). ***** Create Carrier ****************************************** CREATE OBJECT go_carrier EXPORTING iv_name = 'Smile&Fly-Travel'. ***** Insert carrier into business partner list of travel agency go_agency->add_partner( go_carrier ). ***** Passenger Plane ***************************************** CREATE OBJECT go_passenger EXPORTING iv_name = 'LH BERLIN' iv_planetype = '747-400' iv_seats = 345 EXCEPTIONS wrong_planetype = 1. IF sy-subrc = 0. go_carrier->add_airplane( go_passenger ). ENDIF. ***** cargo Plane ********************************************* CREATE OBJECT go_cargo EXPORTING iv_name = 'US Hercules' iv_planetype = '747-200F' iv_cargo = 533 EXCEPTIONS wrong_planetype = 1. IF sy-subrc = 0. go_carrier->add_airplane( go_cargo ). ENDIF. ******* show attributes of all partners of travel_agency ****** go_agency->display_attributes( ). Solution: Include Program BC401_INT_S3_RENTAL *---------------------------------------------------------------------* * CLASS lcl_vehicle DEFINITION *---------------------------------------------------------------------* CLASS lcl_vehicle DEFINITION. PUBLIC SECTION. METHODS: constructor IMPORTING iv_make TYPE string, display_attributes. PRIVATE SECTION. DATA:
196
© Copyright. All rights reserved.
Lesson: Integrating Class Models Using Interfaces
mv_make TYPE string. ENDCLASS.
"lcl_vehicle DEFINITION
*---------------------------------------------------------------------* * CLASS lcl_vehicle IMPLEMENTATION *---------------------------------------------------------------------* CLASS lcl_vehicle IMPLEMENTATION. METHOD constructor. mv_make = iv_make. ENDMETHOD.
"constructor
METHOD display_attributes. WRITE mv_make. ENDMETHOD.
"display_attributes
ENDCLASS.
"lcl_vehicle IMPLEMENTATION
*---------------------------------------------------------------------* * CLASS lcl_truck DEFINITION *---------------------------------------------------------------------* CLASS lcl_truck DEFINITION INHERITING FROM lcl_vehicle. PUBLIC SECTION. METHODS: constructor IMPORTING iv_make TYPE string iv_cargo TYPE s_plan_car, display_attributes REDEFINITION. PRIVATE SECTION. DATA: mv_cargo TYPE s_plan_car. ENDCLASS.
"lcl_truck DEFINITION
*---------------------------------------------------------------------* * CLASS lcl_truck IMPLEMENTATION *---------------------------------------------------------------------* CLASS lcl_truck IMPLEMENTATION. METHOD constructor. super->constructor( iv_make ). mv_cargo = iv_cargo. ENDMETHOD. "constructor METHOD display_attributes. WRITE / icon_ws_truck AS ICON. super->display_attributes( ). WRITE: 20 'Max. Cargo:'(005), mv_cargo. ULINE. ENDMETHOD. "display_attributes ENDCLASS.
© Copyright. All rights reserved.
"lcl_truck IMPLEMENTATION
197
Unit 4: Interfaces and Casting
*---------------------------------------------------------------------* * CLASS lcl_bus DEFINITION *---------------------------------------------------------------------* CLASS lcl_bus DEFINITION INHERITING FROM lcl_vehicle. PUBLIC SECTION. METHODS: constructor IMPORTING iv_make TYPE string iv_passengers TYPE i, display_attributes REDEFINITION. PRIVATE SECTION. DATA: mv_passengers TYPE i. ENDCLASS.
"lcl_bus DEFINITION
*---------------------------------------------------------------------* * CLASS lcl_bus IMPLEMENTATION *---------------------------------------------------------------------* CLASS lcl_bus IMPLEMENTATION. METHOD constructor. super->constructor( iv_make ). mv_passengers = iv_passengers. ENDMETHOD. "constructor METHOD display_attributes. WRITE: / icon_transportation_mode AS ICON. super->display_attributes( ). WRITE: 20 'Max. Passengers: '(006), mv_passengers. ULINE. ENDMETHOD. "display_attributes ENDCLASS.
"lcl_bus IMPLEMENTATION
*---------------------------------------------------------------------* * CLASS lcl_rental DEFINITION *---------------------------------------------------------------------* CLASS lcl_rental DEFINITION. PUBLIC SECTION. INTERFACES: lif_partner. METHODS: constructor IMPORTING iv_name TYPE string, add_vehicle IMPORTING io_vehicle TYPE REF TO lcl_vehicle, display_attributes. PRIVATE SECTION.
198
© Copyright. All rights reserved.
Lesson: Integrating Class Models Using Interfaces
DATA: mv_name TYPE string, mt_vehicles TYPE TABLE OF REF TO lcl_vehicle. ENDCLASS. "lcl_rental DEFINITION *---------------------------------------------------------------------* * CLASS lcl_rental IMPLEMENTATION *---------------------------------------------------------------------* CLASS lcl_rental IMPLEMENTATION. METHOD constructor. mv_name = iv_name. ENDMETHOD.
"constructor
METHOD add_vehicle. APPEND io_vehicle TO mt_vehicles. ENDMETHOD. "add_vehicle METHOD display_attributes. DATA: lo_vehicle TYPE REF TO lcl_vehicle. WRITE: / icon_transport_proposal AS ICON, mv_name. ULINE. ULINE. LOOP AT mt_vehicles INTO lo_vehicle. lo_vehicle->display_attributes( ). ENDLOOP. ENDMETHOD. "display_attributes METHOD lif_partner~display_partner. me->display_attributes( ). ENDMETHOD. "lif_partner~display_partner ENDCLASS.
© Copyright. All rights reserved.
"lcl_rental IMPLEMENTATION
199
Unit 4: Interfaces and Casting
Implementation of Interface Hierarchies
Figure 91: Interface Hierarchy in the Application Example
An interface implementation strongly resembles regular inheritance. With regular inheritance you can define large hierarchies of classes. When we use interfaces instead of classes we call that interface hierarchies. We would like to illustrate this technique with an application example. In this example, you need to know whether it is useful to define a further service for “room reservation” in the interface LIF_PARTNER. In this case, the classes LCL_CARRIER and LCL_RENTAL need to implement the appropriate method because they have integrated with the interface LIF_PARTNER. However, keeping the same semantics is not conceivable for airlines or car rental companies when we implement the "room reservation" service. However, because there are several other business partner types for which this implementation is useful, for example, motels and hotels, the method needs to be defined centrally and not individually for motels and hotels. If we also need to extend the model with other accommodation provider types, for example, guesthouses, then the interface hierarchy needs to be retained.
200
© Copyright. All rights reserved.
Lesson: Integrating Class Models Using Interfaces
Compound Interface in Unified Modeling Language (UML) Notation
Figure 92: Compound Interface in UML Notation
In ABAP Objects, interfaces like regular superclasses can include other interfaces. As with regular inheritance, the interface hierarchies can be of any depth. The including interface is a specialization of the included interface. The including interface is known as a compound interface, represents an extension of the included interface. An included interface represents a component of another interface and is therefore known as a component interface. An interface that does not contain other interfaces in itself is known as an elementary interface. The UML notation corresponds to the implementation of an elementary interface by a class. Definition and Implementation of Compound Interfaces – Syntax
Figure 93: Definition and Implementation of Compound Interfaces – Syntax
© Copyright. All rights reserved.
201
Unit 4: Interfaces and Casting
As with regular inheritance, the implementing class only needs to list the compound interface in order to integrate all components. Nevertheless, the components of the component interfaces keep their original names: component_interface_name~component_name They are therefore not prefixed by the name of the compound interface. All implementations of methods from all higher level interfaces must take place in the first implementing class. Alias names are suitable for short-form syntax when accessing components from different interfaces. If the implementing class contains aliases, it provides a central view of all components. Addressing Components in Compound Interfaces – Syntax
Figure 94: Addressing Components in Compound Interfaces – Syntax
You need to address the components from a compound interface and do cast assignments the same way.
Correct Use of Interfaces
Figure 95: Using Interfaces
202
© Copyright. All rights reserved.
Lesson: Integrating Class Models Using Interfaces
Interfaces are used to describe protocols for using components without connecting any implementation. An intermediate layer is introduced to protect the client from the explicit server, thereby making the client independent. Interfaces enable different classes to be handled uniformly, provided those classes have implemented the interfaces. As with inheritance, you can also perform polymorphism using interface reference variables. As is the case with regular inheritance, the definition of an interface means the abstraction of the implementing classes to a specific aspect. Multiple inheritances can be simulated using interfaces. If several interfaces are included, all components are available to each of the interfaces and you must implement all methods.
© Copyright. All rights reserved.
203
Unit 4: Interfaces and Casting
LESSON SUMMARY You should now be able to:
204
●
Implement downcasts with interfaces
●
Integrate different submodels using interfaces
●
Create and use interface hierarchies
© Copyright. All rights reserved.
Unit 4 Learning Assessment
1. You can access interface components only by using an object reference. Determine whether this statement is true or false. X
True
X
False
2. Which of the following is the main strength of interfaces? Choose the correct answer. X
A Events
X
B Inheritance
X
C Polymorphism
3. ?= is the down-cast assignment operator. Determine whether this statement is true or false. X
True
X
False
4. Which of the following strongly resembles inheritance? Choose the correct answer. X
A Interface
X
B Class
X
C Method
5. Interfaces can include other interfaces. Determine whether this statement is true or false. X
True
X
False
© Copyright. All rights reserved.
205
Unit 4 Learning Assessment - Answers
1. You can access interface components only by using an object reference. Determine whether this statement is true or false. X
True
X
False
2. Which of the following is the main strength of interfaces? Choose the correct answer. X
A Events
X
B Inheritance
X
C Polymorphism
3. ?= is the down-cast assignment operator. Determine whether this statement is true or false. X
True
X
False
4. Which of the following strongly resembles inheritance? Choose the correct answer.
206
X
A Interface
X
B Class
X
C Method
© Copyright. All rights reserved.
Unit 4: Learning Assessment - Answers
5. Interfaces can include other interfaces. Determine whether this statement is true or false. X
True
X
False
© Copyright. All rights reserved.
207
Unit 4: Learning Assessment - Answers
208
© Copyright. All rights reserved.
UNIT 5
Object-Oriented Events
Lesson 1 Implementing Events in Local Classes Exercise 14: Implement Events in Local Classes
210 219
Lesson 2 Implementing Events in Local Interfaces Exercise 15: Implement Handling of Interface Events
232 233
UNIT OBJECTIVES ●
Implement event-controlled method calls
●
Trigger and handle events
●
Register for events
●
Explain visibility sections in event handling
●
Implement events in local interfaces
© Copyright. All rights reserved.
209
Unit 5 Lesson 1 Implementing Events in Local Classes
LESSON OVERVIEW This lesson explains the method of implementing events in local classes. Business Example As a developer, you need to implement event-controlled behavior for your model in ABAP Objects. For this reason, you require the following knowledge: ●
An understanding of how to define and trigger events
●
An understanding of how to events
●
An understanding of how to register events
●
An understanding of how to implement events in local classes
LESSON OBJECTIVES After completing this lesson, you will be able to: ●
Implement event-controlled method calls
●
Trigger and handle events
●
Register for events
●
Explain visibility sections in event handling
Event-Controlled Method Calls
Figure 96: Event-Controlled Method Calls
210
© Copyright. All rights reserved.
Lesson: Implementing Events in Local Classes
Besides attributes and methods, classes and their instances can also contain another type of component called events. Instance events can be triggered by the instances of the class, but static events can be triggered by the class itself. Events can also be defined as interface components. Given the right circumstances, handler methods react to the triggering of this event. This means that the runtime system may call these handler methods after the event has been triggered. In other words, the client usually does not call the handler method directly. This results in a completely different modeling concept. While you are developing the class that triggers the event, you do not need to know anything about the class that is handling it. The triggering class sends a specific message to all classes and, if required, their instances. At the time of development, type of handlers and the number of handlers which may be used are not known. Because of the definition of the handler method, the range of possible results can be narrowed down. However, the results which may occur can be determined only after the event has been triggered. An event can have exporting parameters, which means that, in contrast to the explicit method call, the calling program determines the protocol. In this application example, after an instance in the Vehicle class is created, the instance triggers the event Vehicle Created. This event is received by several instances and is processed differently by each instance. For example, the rental car company handles the purchasing of a vehicle, while the vehicle registration office registers the purchased vehicle.
Caution: Do not confuse this concept of events in object-oriented programming with events in the ABAP runtime system, such as LOAD-OF-PROGRAM, START-OFSELECTION, and so on. Also, do not confuse this concept with background processing or workflow control. Event Handling in a UML Class Diagram
Figure 97: Event Handling in a UML Class Diagram
© Copyright. All rights reserved.
211
Unit 5: Object-Oriented Events
In UML class diagrams, a dotted arrow with the stereotype «handlesEventOf» points from the handling class to the triggering class. The event definition and signature only appear implicitly in the handling class within the handler method. The handler methods are separated from the other methods using the stereotype «eventHandler».
Event Triggering and Handling
Figure 98: Defining and Triggering Events – Syntax
Depending on the status of your application, you may not need to program every step every time. The separation of cause and effect in your programming must be reflected in the way you construct complex applications. Often, the event is already triggered, and all you have to do is create another event handler. Within a class, instance events are defined using the EVENTS statement, while static events are defined using the CLASS-EVENTS statement. Events can only have exporting parameters, which must be passed by value. A class or instance can trigger an event at runtime using the RAISE EVENT statement. Both instance events and static events can be triggered in instance methods. You can trigger static events only in static methods. When an event is triggered, the handler methods that are registered to this event are called in sequence. These handler methods can trigger more events of their own.
212
© Copyright. All rights reserved.
Lesson: Implementing Events in Local Classes
Handling Events – Syntax
Figure 99: Handling Events – Syntax
Instance events or static methods can be defined within a class to handle events. To do so, you must specify the event using the FOR EVENT statement, and the class or interface in which the event was defined using the OF statement. If the event contains exporting parameters and you want to be able to address these syntactically, you must have specified the exporting parameters immediately after IMPORTING in the definition of the method. The handler method’s signature exporting parameters are all that are allowed to be included explicitly than the exporting parameters of the associated event. The parameters are typed by the handler method during the definition of the event. The object that triggers the event determines the protocol. In addition to the explicitly defined exporting parameters, the predefined importing parameter SENDER can always be listed. By using that parameter, you can place a reference to the event-trigger object into the handler method. Therefore, handler methods are usually called by triggered events RAISE EVENT. However, they can also be called explicitly (CALL METHOD). To Trigger and Handle Events This procedure summarizes all of the required programming steps for event controlling: 1. Define an event in a class. The syntax for this is EVENTS eventname, CLASS-EVENTS eventname. 2. Trigger the event in in a method of this class. The syntax for this is RAISE EVENT eventname. 3. Define and implement the handler method in the same or another. The syntax for this is [CLASS -] METHODS … FOR EVENT …. OF. 4. Register handler object or handler class to events at runtime. The syntax for this is SET HANDLER.
© Copyright. All rights reserved.
213
Unit 5: Object-Oriented Events
Event Handler Registration
Figure 100: Event handler registration
The definition of the handler method only specifies how and to which event of which class the method will react. At runtime, it needs to be determined which possible reactions will actually take place and when each of these reactions will happen. When triggering instance events, you also have to specify which event the reaction will trigger. If instance methods are set to carry out the reaction, you also have to specify which instances will perform the reaction. These specifications are collectively known as registration. Registration is always carried out using the trigger. When the event is triggered, the runtime uses the registrations of the trigger to determine which event handler methods need to be called. In this example, handler methods are defined for the event of the vehicle class, the car rental class, and the vehicle registration class. However, you can only predetermine which car rental instances and vehicle registration instances will react to which vehicle instance, and when they will do so. Registrations can also be revoked.
214
© Copyright. All rights reserved.
Lesson: Implementing Events in Local Classes
Registering Event Handling – Syntax
Figure 101: Registering Event Handling – Syntax
Events are registered using the SET HANDLER statement. Registration is only active at program runtime. With instance events, FOR is followed by the reference to the object that triggers the event. The addition ACTIVATION 'X' is optional during registration. To undo the registration, use ACTIVATION ' '. You can register several methods with one SET HANDLER statement: SET HANDLER ref_handler_1->on_eventname_1 ... ref_handler_n->on_eventname_n FOR ... Caution: If several methods were registered to one event, the sequence in which the event handler methods are called is not defined, that is, there is no guaranteed sequence in which the event handler methods are called. With the addition ALL INSTANCES an event handler can be registered for all instances of the class that defines the instance event. This is the only way to register handlers for instances that have not yet been created.
© Copyright. All rights reserved.
215
Unit 5: Object-Oriented Events
Event Handler Deregistration
Figure 102: Registration/Deregistration Handler Tables
Every object or class that defines events has an internal table known as the handler table. All handler methods that are registered to the various events are listed within the handler table. For instance methods, the handler table also contains references to the registered objects.
Hint: Objects that are registered for event handling are not deleted by the garbage collector, even if there are no remaining references to them.
Note: It is possible to add or remove event handlers for a given event while an event handler for this exact event is executed. If a new event handler is registered, then this event handler is added to the end of the sequence and executed when its time comes. If an existing event handler is deregistered, then this handler is deleted immediately from the event handler method sequence.
Visibility Sections in Event Handling Events are subject to the visibility concept and can therefore be considered public, protected, or private. Event handler methods also have visibility attributes. Visibility Sections for Handling Events ●
PUBLIC Can be accessed anywhere
●
PROTECTED Can only be handled within that class or its subclasses
216
© Copyright. All rights reserved.
Lesson: Implementing Events in Local Classes
●
PRIVATE Can only be handled within its class
Visibility of the Handler Method ●
PUBLIC Anywhere in the program
●
PROTECTED Can be handled within that class or its subclasses
●
PRIVATE Can only be handled within its class
Event-handler methods can only have the same or more restricted visibility than the events they refer to.
© Copyright. All rights reserved.
217
Unit 5: Object-Oriented Events
218
© Copyright. All rights reserved.
Unit 5 Exercise 14 Implement Events in Local Classes
Business Example You need to include airplane and vehicle references in the airline and the car rental company’s lists. This process is to be event-controlled. Template: SAPBC401_INT_S3 Solution: SAPBC401_EVE_S1 Trigger and Handle an Event for Airplanes Define an event for the creation of an airplane. Trigger and handle the event so that the reference to the airplane is entered into the airline’s list of airplanes. 1. Use your program ZBC401_##_MAIN (## is your two-digit group number) or copy the template program. Identify the class that is suitable for triggering the event and the class that you should use for handling the event. Use your UML diagram if necessary. 2. Define the public event AIRPLANE_CREATED in class LCL_AIRPLANE. Choose a suitable method of LCL_AIRPLANE and fire the event in its implementation. 3. In class LCL_CARRIER, define a handler method for the event that you just defined (recommended name: ON_AIRPLANE_CREATED). 4. Implement the handler method so that the new airplane is added to the airplane list of the carrier. Hint: You can do that either directly or by calling the existing method ADD_AIRPLANE. In both cases, ensure that the same airplane cannot be added to the list again. Therefore, either delete method ADD_AIRPLANE or make it private. 5. Remove all calls of ADD_AIRPLANE from your main program. 6. Register the new handler method, so that every airplane created was added into the airplane list by the airline.
© Copyright. All rights reserved.
219
Unit 5: Object-Oriented Events
Note: Although this model is unrealistic, we will use it for the time being. You can create a different rule for entering the airplane later. 7. Where could the SET HANDLER statement be executed in the example given? Could this also be done from the main program?
8. Observe the execution of the program in the ABAP Debugger. 9. What would the syntax have to be in this case?
Trigger and Handle an Event for Vehicles Define an event for the creation of a vehicle. Trigger and handle the event so that the reference to the vehicle is entered into the car rental company’s list of vehicles. 1. Remove all calls of ADD_VEHICLE from your main program. 2. Define the public event VEHICLE_CREATED in class LCL_VEHICLE and fire the event in the implementation of the constructor. 3. In class LCL_RENTAL, define and implement a handler method for the event that you just defined (recommended name: ON_VEHICLE_CREATED). 4. Register the new handler method, so that every vehicle was added into the vehicle list by the car rental company. Note: Although this model is unrealistic, we will use it for the time being. A different rule for entering the vehicles could be created later. 5. Observe the execution of the program in the ABAP Debugger.
220
© Copyright. All rights reserved.
Unit 5 Solution 14 Implement Events in Local Classes
Business Example You need to include airplane and vehicle references in the airline and the car rental company’s lists. This process is to be event-controlled. Template: SAPBC401_INT_S3 Solution: SAPBC401_EVE_S1 Trigger and Handle an Event for Airplanes Define an event for the creation of an airplane. Trigger and handle the event so that the reference to the airplane is entered into the airline’s list of airplanes. 1. Use your program ZBC401_##_MAIN (## is your two-digit group number) or copy the template program. Identify the class that is suitable for triggering the event and the class that you should use for handling the event. Use your UML diagram if necessary. a) Carry out this step in the usual manner. For more information refer to the SAP Library. 2. Define the public event AIRPLANE_CREATED in class LCL_AIRPLANE. Choose a suitable method of LCL_AIRPLANE and fire the event in its implementation. a) Refer source code extract from the model solution. 3. In class LCL_CARRIER, define a handler method for the event that you just defined (recommended name: ON_AIRPLANE_CREATED). a) Refer source code extract from the model solution. 4. Implement the handler method so that the new airplane is added to the airplane list of the carrier. Hint: You can do that either directly or by calling the existing method ADD_AIRPLANE. In both cases, ensure that the same airplane cannot be added to the list again. Therefore, either delete method ADD_AIRPLANE or make it private. a) Refer source code extract from the model solution. 5. Remove all calls of ADD_AIRPLANE from your main program. a) Refer source code extract from the model solution.
© Copyright. All rights reserved.
221
Unit 5: Object-Oriented Events
6. Register the new handler method, so that every airplane created was added into the airplane list by the airline. Note: Although this model is unrealistic, we will use it for the time being. You can create a different rule for entering the airplane later. a) Refer source code extract from the model solution. 7. Where could the SET HANDLER statement be executed in the example given? Could this also be done from the main program? Either in the constructor of LCL_CARRIER or in the main program after the creation of the LCL_CARRIER but before the creation of the first airplane. 8. Observe the execution of the program in the ABAP Debugger. a) Carry out this step in the usual manner. Additional information is available in the SAP Library. 9. What would the syntax have to be in this case? SET HANDLER go_carrier->on_airplane_created FOR ALL INSTANCES. Trigger and Handle an Event for Vehicles Define an event for the creation of a vehicle. Trigger and handle the event so that the reference to the vehicle is entered into the car rental company’s list of vehicles. 1. Remove all calls of ADD_VEHICLE from your main program. a) Refer source code extract from the model solution. 2. Define the public event VEHICLE_CREATED in class LCL_VEHICLE and fire the event in the implementation of the constructor. a) Refer source code extract from the model solution. 3. In class LCL_RENTAL, define and implement a handler method for the event that you just defined (recommended name: ON_VEHICLE_CREATED). a) Refer source code extract from the model solution. 4. Register the new handler method, so that every vehicle was added into the vehicle list by the car rental company. Note: Although this model is unrealistic, we will use it for the time being. A different rule for entering the vehicles could be created later. a) Refer source code extract from the model solution. 5. Observe the execution of the program in the ABAP Debugger.
222
© Copyright. All rights reserved.
Lesson: Implementing Events in Local Classes
a) Carry out this step in the usual manner. Additional information about the ABAP Debugger is available in the SAP Library. Include Program BC401_EVE_S1_CARRIER *--------------------------------------------------* * CLASS lcl_airplane DEFINITION *--------------------------------------------------* CLASS lcl_airplane DEFINITION. PUBLIC SECTION. METHODS: constructor IMPORTING iv_name TYPE string iv_planetype TYPE saplane-planetype EXCEPTIONS wrong_planetype, display_attributes. CLASS-METHODS: display_n_o_airplanes, class_constructor. EVENTS: airplane_created. PROTECTED SECTION. CONSTANTS: c_pos_1 TYPE i VALUE 30. PRIVATE SECTION. TYPES: ty_planetypes TYPE STANDARD TABLE OF saplane WITH NON-UNIQUE KEY planetype. DATA: mv_name mv_planetype mv_weight mv_tankcap
TYPE TYPE TYPE TYPE
string, saplane-planetype, saplane-weight, saplane-tankcap.
CLASS-DATA: gv_n_o_airplanes TYPE i, gt_planetypes TYPE ty_planetypes. CLASS-METHODS: get_technical_attributes IMPORTING iv_type TYPE saplane-planetype EXPORTING ev_weight TYPE saplane-weight ev_tankcap TYPE saplane-tankcap EXCEPTIONS wrong_planetype. ENDCLASS.
"lcl_airplane DEFINITION
*-------------------------------------------------*
© Copyright. All rights reserved.
223
Unit 5: Object-Oriented Events
* CLASS lcl_airplane IMPLEMENTATION *-------------------------------------------------* CLASS lcl_airplane IMPLEMENTATION. METHOD class_constructor. SELECT * FROM saplane INTO TABLE gt_planetypes. ENDMETHOD. "class_constructor METHOD constructor. mv_name = iv_name. mv_planetype = iv_planetype. get_technical_attributes( EXPORTING iv_type = iv_planetype IMPORTING ev_weight = mv_weight ev_tankcap = mv_tankcap EXCEPTIONS wrong_planetype = 1 ). IF sy-subrc <> 0. RAISE wrong_planetype. ELSE. gv_n_o_airplanes = gv_n_o_airplanes + 1. RAISE EVENT airplane_created. ENDIF. ENDMETHOD.
"constructor
METHOD display_attributes. ... ENDMETHOD.
"display_attributes
METHOD display_n_o_airplanes. ... ENDMETHOD.
"display_n_o_airplanes
METHOD get_technical_attributes. ... ENDMETHOD. ENDCLASS.
"get_technical_attributes "lcl_airplane IMPLEMENTATION
*-------------------------------------------* * CLASS lcl_cargo_plane DEFINITION *-------------------------------------------* CLASS lcl_cargo_plane DEFINITION INHERITING FROM lcl_airplane. ... ENDCLASS.
"lcl_cargo_plane DEFINITION
*-----------------------------------------------* * CLASS lcl_cargo_plane IMPLEMENTATION
224
© Copyright. All rights reserved.
Lesson: Implementing Events in Local Classes
*-----------------------------------------------* CLASS lcl_cargo_plane IMPLEMENTATION. ... ENDCLASS.
"lcl_cargo_plane IMPLEMENTATION
*------------------------------------------------* * CLASS lcl_passenger_plane DEFINITION *------------------------------------------------* CLASS lcl_passenger_plane DEFINITION INHERITING FROM lcl_airplane. ... ENDCLASS.
"lcl_passenger_plane DEFINITION
*-------------------------------------------------* * CLASS lcl_passenger_plane IMPLEMENTATION *-------------------------------------------------* CLASS lcl_passenger_plane IMPLEMENTATION. ... ENDCLASS.
"lcl_passenger_plane IMPLEMENTATION
*--------------------------------------------------* * CLASS lcl_carrier DEFINITION *--------------------------------------------------* CLASS lcl_carrier DEFINITION. PUBLIC SECTION. INTERFACES lif_partner. METHODS: constructor IMPORTING iv_name TYPE string, display_attributes. PRIVATE SECTION. DATA: mv_name TYPE string, mt_airplanes TYPE TABLE OF REF TO lcl_airplane. METHODS: on_airplane_created FOR EVENT airplane_created OF lcl_airplane IMPORTING sender, display_airplanes. ENDCLASS.
"lcl_carrier DEFINITION
*--------------------------------------------------* * CLASS lcl_carrier IMPLEMENTATION *--------------------------------------------------* CLASS lcl_carrier IMPLEMENTATION. METHOD constructor. mv_name = iv_name. SET HANDLER on_airplane_created FOR ALL INSTANCES.
© Copyright. All rights reserved.
225
Unit 5: Object-Oriented Events
ENDMETHOD.
"constructor
METHOD lif_partner~display_partner. display_attributes( ). ENDMETHOD. "lif_partners~display_partner METHOD on_airplane_created. APPEND sender TO mt_airplanes. ENDMETHOD. "on_airplane_created METHOD display_attributes. SKIP 2. WRITE: icon_flight AS ICON, mv_name. ULINE. ULINE. display_airplanes( ). ENDMETHOD. "display_attributes METHOD display_airplanes. DATA: lo_plane TYPE REF TO lcl_airplane. LOOP AT mt_airplanes INTO lo_plane. lo_plane->display_attributes( ). ENDLOOP. ENDMETHOD. "display_airplanes ENDCLASS.
"lcl_carrier IMPLEMENTATION
Include Program BC401_EVE_S1_RENTAL *-----------------------------------------------* * CLASS lcl_vehicle DEFINITION *-----------------------------------------------* CLASS lcl_vehicle DEFINITION. PUBLIC SECTION. METHODS: constructor IMPORTING iv_make TYPE string, display_attributes. CLASS-METHODS: get_count EXPORTING ev_count TYPE i. EVENTS: vehicle_created. PRIVATE SECTION. DATA: mv_make TYPE string. CLASS-DATA: gv_n_o_vehicles TYPE i. ENDCLASS.
"lcl_vehicle DEFINITION
*-------------------------------------------------* * CLASS lcl_vehicle IMPLEMENTATION *-------------------------------------------------* CLASS lcl_vehicle IMPLEMENTATION. METHOD constructor. mv_make = iv_make. ADD 1 TO gv_n_o_vehicles.
226
© Copyright. All rights reserved.
Lesson: Implementing Events in Local Classes
RAISE EVENT vehicle_created. ENDMETHOD. "constructor METHOD display_attributes. WRITE mv_make. ENDMETHOD. "display_attributes METHOD get_count. ev_count = gv_n_o_vehicles. ENDMETHOD. "get_count ENDCLASS.
"lcl_vehicle IMPLEMENTATION
*-----------------------------------------------* * CLASS lcl_truck DEFINITION *-----------------------------------------------* CLASS lcl_truck DEFINITION INHERITING FROM lcl_vehicle. ... ENDCLASS.
"lcl_truck DEFINITION
*-----------------------------------------------* * CLASS lcl_truck IMPLEMENTATION *-----------------------------------------------* CLASS lcl_truck IMPLEMENTATION. ... ENDCLASS.
"lcl_truck DEFINITION
*-------------------------------------------------* * CLASS lcl_bus DEFINITION *-------------------------------------------------* CLASS lcl_bus DEFINITION INHERITING FROM lcl_vehicle. ... ENDCLASS.
"lcl_bus DEFINITION
*-------------------------------------------------* * CLASS lcl_bus IMPLEMENTATION *-------------------------------------------------* CLASS lcl_bus IMPLEMENTATION. ... ENDCLASS.
"lcl_bus DEFINITION
*-------------------------------------------------* * CLASS lcl_rental DEFINITION *--------------------------------------------------* CLASS lcl_rental DEFINITION. PUBLIC SECTION. INTERFACES: lif_partner. METHODS: constructor IMPORTING iv_name TYPE string,
© Copyright. All rights reserved.
227
Unit 5: Object-Oriented Events
display_attributes. PRIVATE SECTION. DATA: mv_name TYPE string, mt_vehicles TYPE TABLE OF REF TO lcl_vehicle. METHODS: on_vehicle_created FOR EVENT vehicle_created OF lcl_vehicle IMPORTING sender. ENDCLASS.
"lcl_rental DEFINITION
*-------------------------------------------------* * CLASS lcl_rental IMPLEMENTATION *-------------------------------------------------* CLASS lcl_rental IMPLEMENTATION. METHOD lif_partner~display_partner. display_attributes( ). ENDMETHOD. "lif_partners~display_partner METHOD constructor. mv_name = iv_name. SET HANDLER on_vehicle_created FOR ALL INSTANCES. ENDMETHOD. "constructor METHOD on_vehicle_created. APPEND sender TO mt_vehicles. ENDMETHOD. "on_vehicle_created METHOD display_attributes. DATA: lo_vehicle TYPE REF TO lcl_vehicle. WRITE: / icon_transport_proposal AS ICON, mv_name. WRITE: / 'Here comes the vehicle list: '. ULINE. ULINE. LOOP AT mt_vehicles INTO lo_vehicle. lo_vehicle->display_attributes( ). ENDLOOP. ENDMETHOD. "display_attributes ENDCLASS.
"lcl_rental IMPLEMENTATION
Main Program SAPBC401_EVE_S1 REPORT
sapbc401_eve_s1.
TYPE-POOLS icon. INCLUDE bc401_eve_s1_agency. INCLUDE bc401_eve_s1_carrier. INCLUDE bc401_eve_s1_rental. DATA: go_vehicle go_truck
228
TYPE REF TO lcl_vehicle, TYPE REF TO lcl_truck,
© Copyright. All rights reserved.
Lesson: Implementing Events in Local Classes
go_bus go_rental go_agency go_carrier go_airplane go_cargo go_passenger gv_count
TYPE TYPE TYPE TYPE TYPE TYPE TYPE TYPE
REF REF REF REF REF REF REF i.
TO TO TO TO TO TO TO
lcl_bus, lcl_rental, lcl_travel_agency, lcl_carrier, lcl_airplane, lcl_cargo_plane, lcl_passenger_plane,
START-OF-SELECTION. ******************* ******* create travel_agency CREATE OBJECT go_agency EXPORTING iv_name = 'Travel&smile Travel'. ******* create rental CREATE OBJECT go_rental EXPORTING iv_name = 'Happy Car Rental'. ***** Insert rental company into partner list ***** of travel agency go_agency->add_partner( go_rental ). ******* create truck CREATE OBJECT go_truck EXPORTING iv_make = 'MAN' iv_cargo = 45. * go_rental->add_vehicle( go_truck ). ******* create truck CREATE OBJECT go_bus EXPORTING iv_make = 'Mercedes' iv_passengers = 80. * go_rental->add_vehicle( go_bus ). ******* create truck CREATE OBJECT go_truck EXPORTING iv_make = 'VOLVO' iv_cargo = 48. * go_rental->add_vehicle( go_truck ). ***** Create Carrier CREATE OBJECT go_carrier EXPORTING iv_name = 'Smile&Fly-Travel'. ***** Insert carrier into business partner list ***** of travel agency go_agency->add_partner( go_carrier ). ***** Passenger Plane CREATE OBJECT go_passenger EXPORTING iv_name = 'LH BERLIN' iv_planetype = '747-400' iv_seats = 345 EXCEPTIONS
© Copyright. All rights reserved.
229
Unit 5: Object-Oriented Events
wrong_planetype = 1. *
IF sy-subrc = 0. go_carrier->add_airplane( go_passenger ). ELSE. WRITE: / icon_failure AS ICON, 'Wrong plane type'. ENDIF.
***** cargo Plane CREATE OBJECT go_cargo EXPORTING iv_name = 'US Hercules' iv_planetype = '747-200F' iv_cargo = 533 EXCEPTIONS wrong_planetype = 1. IF sy-subrc = 0. * go_carrier->add_airplane( go_cargo ). ELSE. WRITE: / icon_failure AS ICON, 'Wrong plane type'. ENDIF. ***** show attributes of all partners travel agency go_agency->display_attributes( ).
230
© Copyright. All rights reserved.
Lesson: Implementing Events in Local Classes
LESSON SUMMARY You should now be able to: ●
Implement event-controlled method calls
●
Trigger and handle events
●
Register for events
●
Explain visibility sections in event handling
© Copyright. All rights reserved.
231
Unit 5 Lesson 2 Implementing Events in Local Interfaces
LESSON OVERVIEW This lesson explains the implementation of events in local interfaces. Business Example As a developer, you need to implement events in local classes of the airplane. For this reason, you require the following knowledge: ●
An understanding of events
●
An understanding of interfaces
●
An understanding of implementing events in local interfaces
LESSON OBJECTIVES After completing this lesson, you will be able to: ●
Implement events in local interfaces
Events in Local Interfaces Events can be defined as interface components. Triggering and handling events are done the same way as in classes. The steps to implement event handling for Interfaces are as follows: 1. Define event in an interfaces 2. Trigger the interface event in implementing classes 3. Handle interface event in handler class (using class) 4. Register event handling
232
© Copyright. All rights reserved.
Unit 5 Exercise 15 Implement Handling of Interface Events
Business Example Airline and car rental company references are to be entered into the travel agent’s list. This process is to be event-controlled. Be sure to create your program so that it can be easily extended to manage additional business partners of the travel agent in the future. Template: SAPBC401_EVE_S1 Solution: SAPBC401_EVE_S2 Define an event for the creation of a business partner. Trigger and handle the event so that the reference to the business partner is entered into the travel agent’s list of partners. 1. Use your ZBC401_##_MAIN program or copy the model solution from the previous exercise (where ## is your two-digit group number). 2. Remove the calls of the method ADD_PARTNER from your main program. Note: The entry of a business partner reference into the travel agent’s list is to be event-controlled. 3. If necessary, examine your UML diagram. Which class or interface defines the event? Which class or interface triggers it? Which class or interface handles it?
If applicable, illustrate the relationships in your UML diagram. 4. Define the event PARTNER_CREATED and trigger it using a suitable method in all classes that implement the interface. 5. Remove the method ADD_PARTNER in the class LCL_TRAVEL_AGENCY. Replace it by a handler method for the event that you just defined (suggested name: ON_PARTNER_CREATED). 6. Register the new handler method, so that every business partner created was added into the partner list by the travel agency.
© Copyright. All rights reserved.
233
Unit 5: Object-Oriented Events
Note: Although this model is unrealistic, we will use it for the time being. A different rule for entering the business partner can be created later. 7. Observe the execution of the program in the ABAP Debugger.
234
© Copyright. All rights reserved.
Unit 5 Solution 15 Implement Handling of Interface Events
Business Example Airline and car rental company references are to be entered into the travel agent’s list. This process is to be event-controlled. Be sure to create your program so that it can be easily extended to manage additional business partners of the travel agent in the future. Template: SAPBC401_EVE_S1 Solution: SAPBC401_EVE_S2 Define an event for the creation of a business partner. Trigger and handle the event so that the reference to the business partner is entered into the travel agent’s list of partners. 1. Use your ZBC401_##_MAIN program or copy the model solution from the previous exercise (where ## is your two-digit group number). a) Carry out this step in the usual manner. For more information, refer to the SAP Library. 2. Remove the calls of the method ADD_PARTNER from your main program. Note: The entry of a business partner reference into the travel agent’s list is to be event-controlled. a) See the source code extract from the model solution. 3. If necessary, examine your UML diagram. Which class or interface defines the event? Which class or interface triggers it? Which class or interface handles it?
If applicable, illustrate the relationships in your UML diagram. a) Speak to your instructor if you have any questions. 4. Define the event PARTNER_CREATED and trigger it using a suitable method in all classes that implement the interface. a) See the source code extract from the model solution. 5. Remove the method ADD_PARTNER in the class LCL_TRAVEL_AGENCY. Replace it by a handler method for the event that you just defined (suggested name: ON_PARTNER_CREATED). a) See the source code extract from the model solution.
© Copyright. All rights reserved.
235
Unit 5: Object-Oriented Events
6. Register the new handler method, so that every business partner created was added into the partner list by the travel agency. Note: Although this model is unrealistic, we will use it for the time being. A different rule for entering the business partner can be created later. a) See the source code extract from the model solution. 7. Observe the execution of the program in the ABAP Debugger. a) Carry out this step in the usual manner. Additional information about the ABAP Debugger is available in the SAP Library. Solution - Include Program BC401_EVE_S2_AGENCY *-----------------------------------------------* * INTERFACE lif_partners *&----------------------------------------------* INTERFACE lif_partner. METHODS: display_partner. EVENTS: partner_created. ENDINTERFACE. "lif_partners *------------------------------------------------* * CLASS lcl_travel_agency DEFINITION *------------------------------------------------* CLASS lcl_travel_agency DEFINITION. PUBLIC SECTION. METHODS: constructor IMPORTING iv_name TYPE string, display_agency_partners, display_attributes. PRIVATE SECTION. DATA: mv_name TYPE string, mt_partners TYPE TABLE OF REF TO lif_partner. METHODS: on_partner_created FOR EVENT partner_created OF lif_partner IMPORTING sender. ENDCLASS. "lcl_travel_agency DEFINITION *-------------------------------------------------* * CLASS lcl_travel_agency IMPLEMENTATION *-------------------------------------------------* CLASS lcl_travel_agency IMPLEMENTATION. METHOD display_attributes. WRITE: / icon_private_files AS ICON, 'Travel Agency:'(007), mv_name. SKIP. display_agency_partners( ). ENDMETHOD.
"display_attributes
METHOD display_agency_partners.
236
© Copyright. All rights reserved.
Lesson: Implementing Events in Local Interfaces
DATA: lo_partner TYPE REF TO lif_partner. WRITE 'Here are the partners of the travel agency:'(008). ULINE. LOOP AT mt_partners INTO lo_partner. lo_partner->display_partner( ). ENDLOOP. ENDMETHOD.
"display_agency_partners
METHOD constructor. mv_name = iv_name. SET HANDLER on_partner_created FOR ALL INSTANCES. ENDMETHOD. "constructor METHOD on_partner_created. APPEND sender TO mt_partners. ENDMETHOD. "on_partner_created ENDCLASS.
"lcl_travel_agency IMPLEMENTATION
Solution - Include Program BC401_EVE_S2_RENTAL *--------------------------------------------------* * CLASS lcl_vehicle DEFINITION *--------------------------------------------------* CLASS lcl_vehicle DEFINITION. ... ENDCLASS. "lcl_vehicle DEFINITION *--------------------------------------------------* * CLASS lcl_vehicle IMPLEMENTATION *--------------------------------------------------* CLASS lcl_vehicle IMPLEMENTATION. ... ENDCLASS. "lcl_vehicle IMPLEMENTATION *--------------------------------------------------* * CLASS lcl_truck DEFINITION *--------------------------------------------------* CLASS lcl_truck DEFINITION INHERITING FROM lcl_vehicle. ... ENDCLASS. "lcl_truck DEFINITION *--------------------------------------------------* * CLASS lcl_truck IMPLEMENTATION *--------------------------------------------------* CLASS lcl_truck IMPLEMENTATION. ... ENDCLASS. "lcl_truck DEFINITION *--------------------------------------------------* * CLASS lcl_bus DEFINITION *--------------------------------------------------* CLASS lcl_bus DEFINITION INHERITING FROM lcl_vehicle. ... ENDCLASS. "lcl_bus DEFINITION
© Copyright. All rights reserved.
237
Unit 5: Object-Oriented Events
*--------------------------------------------------* * CLASS lcl_bus IMPLEMENTATION *--------------------------------------------------* CLASS lcl_bus IMPLEMENTATION. ... ENDCLASS. "lcl_bus DEFINITION *--------------------------------------------------* * CLASS lcl_rental DEFINITION *--------------------------------------------------* CLASS lcl_rental DEFINITION. ... ENDCLASS. "lcl_rental DEFINITION *--------------------------------------------------* * CLASS lcl_rental IMPLEMENTATION *--------------------------------------------------* CLASS lcl_rental IMPLEMENTATION. METHOD lif_partner~display_partner. display_attributes( ). ENDMETHOD. "lif_partners~display_partner METHOD constructor. mv_name = iv_name. SET HANDLER on_vehicle_created FOR ALL INSTANCES. RAISE EVENT lif_partner~partner_created. ENDMETHOD.
"constructor
METHOD on_vehicle_created. APPEND sender TO mt_vehicles. ENDMETHOD. "on_vehicle_created METHOD display_attributes. ... ENDMETHOD. "display_attributes ENDCLASS.
"lcl_rental IMPLEMENTATION
Solution - Include Program BC401_EVE_S2_CARRIER *-------------------------------------------------* * CLASS lcl_airplane DEFINITION *-------------------------------------------------* CLASS lcl_airplane DEFINITION. ... ENDCLASS. "lcl_airplane DEFINITION *-------------------------------------------------* * CLASS lcl_airplane IMPLEMENTATION *-------------------------------------------------* CLASS lcl_airplane IMPLEMENTATION. ... ENDCLASS. "lcl_airplane IMPLEMENTATION *-------------------------------------------------*
238
© Copyright. All rights reserved.
Lesson: Implementing Events in Local Interfaces
* CLASS lcl_cargo_plane DEFINITION *-------------------------------------------------* CLASS lcl_cargo_plane DEFINITION INHERITING FROM lcl_airplane. ... ENDCLASS. "lcl_cargo_plane DEFINITION *-------------------------------------------------* * CLASS lcl_cargo_plane IMPLEMENTATION *-------------------------------------------------* CLASS lcl_cargo_plane IMPLEMENTATION. ... ENDCLASS. "lcl_cargo_plane IMPLEMENTATION *-------------------------------------------------* * CLASS lcl_passenger_plane DEFINITION *-------------------------------------------------* CLASS lcl_passenger_plane DEFINITION INHERITING FROM lcl_airplane. ... ENDCLASS. "lcl_passenger_plane DEFINITION *-------------------------------------------------* * CLASS lcl_passenger_plane IMPLEMENTATION *-------------------------------------------------* CLASS lcl_passenger_plane IMPLEMENTATION. ... ENDCLASS. "lcl_passenger_plane IMPLEMENTATION *-------------------------------------------------* * CLASS lcl_carrier DEFINITION *-------------------------------------------------* CLASS lcl_carrier DEFINITION. ... ENDCLASS. "lcl_carrier DEFINITION *-------------------------------------------------* * CLASS lcl_carrier IMPLEMENTATION *-------------------------------------------------* CLASS lcl_carrier IMPLEMENTATION. METHOD constructor. mv_name = iv_name. SET HANDLER on_airplane_created FOR ALL INSTANCES. RAISE EVENT lif_partner~partner_created. ENDMETHOD. "constructor METHOD lif_partner~display_partner. display_attributes( ). ENDMETHOD. "lif_partners~display_partner METHOD on_airplane_created. APPEND sender TO mt_airplanes. ENDMETHOD. "on_airplane_created METHOD display_attributes. ... ENDMETHOD. "display_attributes METHOD display_airplanes. ... ENDMETHOD. "display_airplanes ENDCLASS.
© Copyright. All rights reserved.
"lcl_carrier IMPLEMENTATION
239
Unit 5: Object-Oriented Events
Solution - Main Program SAPBC401_EVE_S2 REPORT sapbc401_eve_s2. TYPE-POOLS icon. INCLUDE bc401_eve_s2_agency. INCLUDE bc401_eve_s2_carrier. INCLUDE bc401_eve_s2_rental. DATA: go_vehicle TYPE REF TO lcl_vehicle, go_truck TYPE REF TO lcl_truck, go_bus TYPE REF TO lcl_bus, go_rental TYPE REF TO lcl_rental, go_passenger TYPE REF TO lcl_passenger_plane, go_cargo TYPE REF TO lcl_cargo_plane, go_carrier TYPE REF TO lcl_carrier, go_agency TYPE REF TO lcl_travel_agency. START-OF-SELECTION. ******************* ******* create travel_agency CREATE OBJECT go_agency EXPORTING iv_name = 'Travel&Smile Travel'. ******* create rental CREATE OBJECT go_rental EXPORTING iv_name = 'Happy Car Rental'. * go_agency->add_partner( go_rental ). ******* create truck CREATE OBJECT go_truck EXPORTING iv_make = 'MAN' iv_cargo = 45. ******* create truck CREATE OBJECT go_bus EXPORTING iv_name = 'Mercedes' iv_passengers = 80. ******* create truck CREATE OBJECT go_truck EXPORTING iv_make = 'VOLVO' iv_cargo = 48. ***** Create Carrier CREATE OBJECT go_carrier EXPORTING iv_name = 'Smile&Fly-Travel'. * go_agency->add_partner( go_rental ).
240
© Copyright. All rights reserved.
Lesson: Implementing Events in Local Interfaces
***** Passenger Plane CREATE OBJECT go_passenger EXPORTING iv_name = 'LH BERLIN' iv_planetype = '747-400' iv_seats = 345 EXCEPTIONS wrong_planetype = 1. IF sy-subrc <> 0. WRITE: / icon_failure AS ICON, 'Wrong plane type'. ENDIF. ***** cargo Plane CREATE OBJECT go_cargo EXPORTING iv_name = 'US Hercules' iv_planetype = '747-200F' iv_cargo = 533 EXCEPTIONS wrong_planetype = 1. IF sy-subrc <> 0. WRITE: / icon_failure AS ICON, 'Wrong plane type'. ENDIF. ******* show attributes of all partners of travel_agency go_agency->display_attributes( ).
© Copyright. All rights reserved.
241
Unit 5: Object-Oriented Events
LESSON SUMMARY You should now be able to: ●
242
Implement events in local interfaces
© Copyright. All rights reserved.
Unit 5 Learning Assessment
1. Which of the following cannot be defined as interface components? Choose the correct answer. X
A Attributes
X
B Methods
X
C Events
X
D Classes
2. Which of the following statements is used to trigger events? Choose the correct answer. X
A CLASS-EVENTS
X
B RAISE EVENT
X
C EVENTS
X
D FOR EVENTS
3. You can trigger static events only in static methods. Determine whether this statement is true or false. X
True
X
False
4. Which of the following is specified by the definition of the handler method? Choose the correct answer. X
A Which method will react to which event of which class
X
B Which instances will perform the reaction
© Copyright. All rights reserved.
243
Unit 5: Learning Assessment
5. Handler methods are registered using the SET HANDLER statement. Registration is only active at program runtime. Determine whether this statement is true or false. X
True
X
False
6. Which visibility section would an event need to be defined in, to ensure that it can only be handled in the class itself and its subclasses? Choose the correct answer.
244
X
A Public
X
B Protected
X
C Private
© Copyright. All rights reserved.
Unit 5 Learning Assessment - Answers
1. Which of the following cannot be defined as interface components? Choose the correct answer. X
A Attributes
X
B Methods
X
C Events
X
D Classes
2. Which of the following statements is used to trigger events? Choose the correct answer. X
A CLASS-EVENTS
X
B RAISE EVENT
X
C EVENTS
X
D FOR EVENTS
3. You can trigger static events only in static methods. Determine whether this statement is true or false. X
True
X
False
4. Which of the following is specified by the definition of the handler method? Choose the correct answer. X
A Which method will react to which event of which class
X
B Which instances will perform the reaction
© Copyright. All rights reserved.
245
Unit 5: Learning Assessment - Answers
5. Handler methods are registered using the SET HANDLER statement. Registration is only active at program runtime. Determine whether this statement is true or false. X
True
X
False
6. Which visibility section would an event need to be defined in, to ensure that it can only be handled in the class itself and its subclasses? Choose the correct answer.
246
X
A Public
X
B Protected
X
C Private
© Copyright. All rights reserved.
UNIT 6
Object-Oriented Repository Objects
Lesson 1 Creating Global Classes Exercise 16: Implement a Global Class
248 257
Lesson 2 Defining and Implementing Global Interfaces Exercise 17: Import and Implement a Global Interface
267 271
Lesson 3 Implementing Inheritance in Global Classes
282
UNIT OBJECTIVES ●
Create global classes
●
Test global classes
●
Use global classes
●
Define and implement global interfaces
●
Import local classes and interfaces
●
Generate UML diagrams for global classes
●
Implement inheritance in global classes
●
Change the display of components in global classes
© Copyright. All rights reserved.
247
Unit 6 Lesson 1 Creating Global Classes
LESSON OVERVIEW This lesson explains how to create global classes. Business Example As a developer, you must create a global ABAP class for airplanes that can be accessed by all other ABAP Objects in the SAP system. For this reason, you require the following knowledge: ●
An understanding of global classes
●
An understanding of how to test and use global classes
LESSON OBJECTIVES After completing this lesson, you will be able to: ●
Create global classes
●
Test global classes
●
Use global classes
Definition of Global Classes Note: A large number of screenshots and screen illustrations are used in the lesson. Note that the appearance of some of the icons or menus depends on the release level. As with subroutines, use local classes or interfaces only within the program in which they are defined and implemented. The CLASS statement is a local declarative statement in the program. As the TYPES statement defines local data types, the CLASS statement defines local object types. On the other hand, global classes or global interfaces are individual repository objects with all the standard ABAP Workbench features such as active integration, versioning, transport system. The namespace convention, for example Y*, Z*, or a special customer namespace is the same as that name used for the namespace of other repository objects. Therefore, a special maintenance tool is available in the ABAP Workbench, that is the Class Builder. In case you are unsure about a certain feature in the Class Builder, you are advised to use the Quickinfo. It is the explanatory text that appears when you place the cursor over an icon and leave it there for a short time.
248
© Copyright. All rights reserved.
Lesson: Creating Global Classes
Creating Global Classes in the Object Navigator
Figure 103: Creating Global Classes in the Object Navigator
As with other repository objects, the separate navigation area of the Object Navigator makes it the ideal development tool for all repository objects. The easiest way to create a new global class is to use the context menu in the navigation area. To do so, first select the package node or select the class node within a package. A dialog box appears that offers you some choices for the new class. Select Usual ABAP class. The global class or global interface is then displayed in the Class Builder table in the editor area of the Object Navigator.
© Copyright. All rights reserved.
249
Unit 6: Object-Oriented Repository Objects
Definition of Attributes in a Global Class
Figure 104: Definition of Attributes
Choose the Attributes tab page to open a list of all attribute definitions in the class. You can also define new attributes here. You can use the input help when defining the types of attributes. Remember to use meaningful short descriptions.
Create Methods in Global Class
Figure 105: Definition of Methods
250
© Copyright. All rights reserved.
Lesson: Creating Global Classes
Choose the Methods tab page to open a list of all method definitions in the class. You can define new methods here. Remember to use meaningful short descriptions. There are separate editor windows for the method parameters (also known as method signature) and the implementation. Choose the Constructor pushbutton to define an instance constructor. The system automatically chooses the name of constructor.
Hint: Methods can be transported separately because each implementation is stored in an own ABAP include. Definition of Method Parameters
Figure 106: Definition of Method Signatures
In the method list, select a method and choose the Parameter button to go to the signature maintenance. You can define new formal parameters here. You can use the input help when defining the type of the parameters. Remember to use meaningful short descriptions. You can browse between the signatures with the help of the Previous Method or Next Methods button. Choose the Methods button to return to the method list.
© Copyright. All rights reserved.
251
Unit 6: Object-Oriented Repository Objects
Implementation of Methods
Figure 107: Implementation of Methods
In the method list, select a method by double-clicking it. Alternatively, choose the Source code button to go to the source text maintenance if a method is already selected. You can implement the methods here.
Hint: Choose the relevant button to display the method’s signature.
252
© Copyright. All rights reserved.
Lesson: Creating Global Classes
Displaying the Method Definition
Figure 108: Displaying the Method Definition
Choose Goto → Method definition to change the attributes of your method during implementation. Optionally, you can define an event handler method on the Attributes tab page in the dialog box. Definition of Components Using the Navigation Area
Figure 109: Definition of Components Using the Navigation Area
You can define attributes, methods, or events in the context menu of the Object Navigator’s navigation area. The properties are then maintained in a dialog box, and not in the table.
© Copyright. All rights reserved.
253
Unit 6: Object-Oriented Repository Objects
Hint: Choose Class → Print or Method → Print to print selected portions of the source text.
Class Builder Testing Environment
Figure 110: The Class Builder Testing Environment
You can test active global classes by choosing menu path Class → Run → In Test Environment, choosing the corresponding application toolbar button, or press F8. Static attributes and static methods are directly accessible in the test environment. Instance attributes and instance methods are accessible after instance creation only. You can create an instance using the Create Instance button. The system only lists the public components. Methods can be tested using the Execute Method button. The following are the steps to trigger events in a class: 1. Select an event. 2. Choose Handler to register a standard method for the event. 3. Call a method in which the event trigger was implemented. The event that was triggered and all of the exported actual parameters are displayed in a list.
254
© Copyright. All rights reserved.
Lesson: Creating Global Classes
Use of Global Classes in the ABAP Editor
Figure 111: Separation of Navigation and Editing Areas in the Object Navigator
Like other repository objects, global classes and interfaces are added in the navigation area of the object navigator. This way, the discussed advantages also apply to global classes and interfaces. Object Instantiation Using Drag and Drop
Figure 112: Object Instantiation Using Drag and Drop
In the navigation area, select a class name and move it to the editing area. This action creates a CREATE OBJECT statement. Then, add the reference variable and the actual parameters, if applicable, to the statement.
© Copyright. All rights reserved.
255
Unit 6: Object-Oriented Repository Objects
Alternatively, you can also choose the Pattern button. You can find the CREATE OBJECT statement by selecting ABAP Objects Patterns. You can generate the statement using the input help. Method Calls Using Drag and Drop
Figure 113: Method Calls Using Drag and Drop
In the navigation area, select a method name and move it to the editing area. This action creates a CREATE METHOD statement. Then, add the reference variable and the actual parameters, if applicable, to the statement. Alternatively, you can also choose the Pattern button. The CALL METHOD statement is under ABAP Objects Pattern. You can generate the statement using the input help.
Note: To generate patterns, enable the modern functional writing style for method calls. Choose Utilities → Settings → Pattern and select the Functional Writing Style for Call Method checkbox.
256
© Copyright. All rights reserved.
Unit 6 Exercise 16 Implement a Global Class
Business Example You want to create a global class to represent hotels.
Note: This exercise uses the main program ZBC401_##_MAIN completed in the previous exercise. If not completed, copy the model solution with its INCLUDES from the previous exercise. In the exercises for this course, when the input values include ##, replace ## with your group number. Template SAPBC401_EVE_S2 (main program) Solution SAPBC401_GCL_S1 (main program) CL_HOTEL (global class) Create a Global Class Create a global class for hotels. 1. Create the global class ZCL_##_HOTEL (## is your two-digit group number). 2. Define a private constant named C_POS_1 of type I, with the value 30. 3. Define a private instance attribute named MV_NAME, or type STRING. 4. Define a private instance attribute named MV_BEDS, of type I. 5. Define a private static attribute named GV_N_O_HOTELS, of type I. 6. Define the following methods in the class: Table 4: Methods Method Name
Method Characteristics
CONSTRUCTOR
Instance constructor for setting the private attributes with the import parameters IV_NAME and IV_BEDS, and to increment the counter GV_N_O_HOTELS
DISPLAY_ATTRIBUTES
Public instance method for displaying the attributes
© Copyright. All rights reserved.
257
Unit 6: Object-Oriented Repository Objects
Method Name
Method Characteristics
DISPLAY_N_O_HOTELS
Public static method to display the number of created hotel instances
Test the Class Check your work. 1. Save, check, and activate your class. 2. Test your class in the Class Builder testing environment. Use the Hotel Class in Your Program Create an instance of your global class for hotels in your main program. 1. Define a reference variable, specify your global hotel class as the type, and create an instance. 2. If you have not done the optional exercise, where you add business partners to the travel agency through event handling, try to call method ADD_PARTNER for the hotel. 3. Why can the hotel not yet be integrated into the list of travel agency business partners?
4. Could the local interface LIF_PARTNER be implemented in the global class for hotels?
258
© Copyright. All rights reserved.
Unit 6 Solution 16 Implement a Global Class
Business Example You want to create a global class to represent hotels.
Note: This exercise uses the main program ZBC401_##_MAIN completed in the previous exercise. If not completed, copy the model solution with its INCLUDES from the previous exercise. In the exercises for this course, when the input values include ##, replace ## with your group number. Template SAPBC401_EVE_S2 (main program) Solution SAPBC401_GCL_S1 (main program) CL_HOTEL (global class) Create a Global Class Create a global class for hotels. 1. Create the global class ZCL_##_HOTEL (## is your two-digit group number). a) In transaction SE80, in the unnamed dropdown list on the left of the screen, choose Class/ Interface and specify the name of the new global class, ZCL_##_HOTEL. b) Press Enter, a Create Class/Interface dialog box appears. c) To create the class, choose Yes. d) In the Create Class ZCL_##_HOTEL dialog box, enter a short description for the global class and choose Save. e) In the Create Object Directory Entry dialog box, enter your package name and choose Save. The Prompt for transportable Workbench request dialog box displays. f) In the Prompt for transportable Workbench request dialog box, enter the request name supplied by your instructor. Choose Continue. 2. Define a private constant named C_POS_1 of type I, with the value 30. a) Choose the Attributes tab. b) In the attribute field, enter C_POS_1. c) In the Level field, use the input help to choose Constant.
© Copyright. All rights reserved.
259
Unit 6: Object-Oriented Repository Objects
d) In the Visibility field, use the input help to choose Private. e) In the Associated Type field, enterI. f) In the Description field, enterOutput Position. g) In the Initial Value field, enter30. 3. Define a private instance attribute named MV_NAME, or type STRING. a) In the Attribute field, enter MV_NAME. b) In the Level field, use the input help to choose Instance Attribute. c) In the Visibility field, use the input help to choose Private. d) In the Associated Type field, enterSTRING. e) In the Description field, enter Hotel Name. 4. Define a private instance attribute named MV_BEDS, of type I. a) In the Attribute field, enter MV_BEDS. b) In the Level field, use the input help to choose Instance Attribute. c) In the Visibility field, use the value input help to choose Private. d) In the Associated Type field, enter I. e) In the Description field, enter Number of Beds. 5. Define a private static attribute named GV_N_O_HOTELS, of type I. a) In the Attribute field, enter GV_N_O_HOTELS. b) In the Level field, use the input help to choose Static Attribute. c) In the Visibility field, use the input help to choose Private. d) In the Associated Type field, enterI. e) In the Description field, enter Number of Hotels. 6. Define the following methods in the class: Table 4: Methods Method Name
Method Characteristics
CONSTRUCTOR
Instance constructor for setting the private attributes with the import parameters IV_NAME and IV_BEDS, and to increment the counter GV_N_O_HOTELS
DISPLAY_ATTRIBUTES
Public instance method for displaying the attributes
DISPLAY_N_O_HOTELS
Public static method to display the number of created hotel instances
a) Choose the Methods tab.
260
© Copyright. All rights reserved.
Lesson: Creating Global Classes
b) Choose the Create Constructor button on the application toolbar. c) Put your cursor on method CONSTRUCTOR and choose the Parameter button. d) In the Parameter field, enter IV_NAME. e) In the Associated Type field, enter STRING. f) In the Parameter field, enter IV_BEDS. g) In the Associated Type field, enter I. h) Choose the Back to Methods button. i) Put your cursor in the Method field under CONSTRUCTOR and enter DISPLAY_ATTRIBUTES. j) In the Level field, use the value selector to choose Instance Method. k) In the Visibility field, use the value selector to choose Public. l) In the Method field under DISPLAY_ATTRIBUTES, enter DISPLAY_N_O_HOTELS. m) In the Level field, use the value selector to choose Static Method. n) In the Visibility field, use the value selector to choose Public. o) Double-click the CONSTRUCTOR method. Choose Yes to save the class. Enter the code from the model solution. p) Choose Save, then Back. q) Double-click the DISPLAY_ATTRIBUTES method. Choose Yes to save the class. Enter the code from the model solution. r) Choose Save, then Back. s) Double-click the DISPLAY_N_O_HOTELS method. Choose Yes to save the class. Enter the code from the model solution. t) Choose Save, then Back. Test the Class Check your work. 1. Save, check, and activate your class. a) Save your class. b) To check your class, on the application toolbar choose the Check button. c) To activate your class, on the application toolbar choose the Activate button. 2. Test your class in the Class Builder testing environment. a) To test your class, press F8. All methods which can be tested will be displayed. At first only the DISPLAY_N_O_HOTELS will be listed, since all other methods are instance methods. b) To test this method, choose the Execute button next to DISPLAY_N_O_HOTELS. c) Choose the Create Instance button on the toolbar.
© Copyright. All rights reserved.
261
Unit 6: Object-Oriented Repository Objects
The parameters of the instance constructor will be displayed. d) Choose the Edit Long Field of Structure button next to IV_NAME, and enter a test name. Choose Back. e) Enter a number for the parameter IV_BEDS. f) Choose the Create Instance button. Now that the test object has been created, the method DISPLAY_ATTRIBUTES is displayed in the test environment, along with method DISPLAY_N_O_HOTELS. g) Choose the Execute button for method DISPLAY_ATTRIBUTES, and verify the output. Use the Hotel Class in Your Program Create an instance of your global class for hotels in your main program. 1. Define a reference variable, specify your global hotel class as the type, and create an instance. a) See source text excerpt from the model solution. 2. If you have not done the optional exercise, where you add business partners to the travel agency through event handling, try to call method ADD_PARTNER for the hotel. a) Perform in the same way as for the carrier and the car rental company. 3. Why can the hotel not yet be integrated into the list of travel agency business partners? The global class for hotels does not implement the interface that is used by the travel agency class. 4. Could the local interface LIF_PARTNER be implemented in the global class for hotels? No, global classes can only implement global interfaces. Therefore, the local interface must be replaced with a global one. This is performed in the next exercise. a) Model solution as follows: Solution: Main Program SAPBC401_GCL_S1 REPORT
sapbc401_gcl_s1.
TYPE-POOLS icon. INCLUDE bc401_gcl_s1_agency. INCLUDE bc401_gcl_s1_carrier. INCLUDE bc401_gcl_s1_rental. DATA: go_hotel go_vehicle go_truck go_bus go_rental go_passenger go_cargo go_carrier go_agency
262
TYPE TYPE TYPE TYPE TYPE TYPE TYPE TYPE TYPE
REF REF REF REF REF REF REF REF REF
TO TO TO TO TO TO TO TO TO
cl_hotel, lcl_vehicle, lcl_truck, lcl_bus, lcl_rental, lcl_passenger_plane, lcl_cargo_plane, lcl_carrier, lcl_travel_agency.
© Copyright. All rights reserved.
Lesson: Creating Global Classes
START-OF-SELECTION. ******************* ******* create travel_agency CREATE OBJECT go_agency EXPORTING iv_name = 'Travel&Smile Travel'. ******* create hotel CREATE OBJECT go_hotel EXPORTING iv_name = 'Sleep Well Hotel' iv_beds = 345. * hotel not added to partner list * does not implement interface * go_agency->add_partner( go_hotel ) ******* create rental CREATE OBJECT go_rental EXPORTING iv_name = 'Happy Car Rental'. * go_agency->add_partner( go_rental ). ******* create truck CREATE OBJECT go_truck EXPORTING iv_make = 'MAN' iv_cargo = 45. ******* create truck CREATE OBJECT go_bus EXPORTING iv_make = 'Mercedes' iv_passengers = 80. ******* create truck CREATE OBJECT go_truck EXPORTING iv_make = 'VOLVO' iv_cargo = 48. ***** Create Carrier CREATE OBJECT go_carrier EXPORTING iv_name = 'Smile&Fly-Travel'. * go_agency->add_partner( go_rental ). ***** Passenger Plane CREATE OBJECT go_passenger EXPORTING iv_name = 'LH BERLIN' iv_planetype = '747-400' iv_seats = 345 EXCEPTIONS wrong_planetype = 1. IF sy-subrc <> 0. WRITE: / icon_failure AS ICON, 'Wrong plane type'. ENDIF.
© Copyright. All rights reserved.
263
Unit 6: Object-Oriented Repository Objects
***** cargo Plane CREATE OBJECT go_cargo EXPORTING iv_name = 'US Hercules' iv_planetype = '747-200F' iv_cargo = 533 EXCEPTIONS wrong_planetype = 1. IF sy-subrc <> 0. WRITE: / icon_failure AS ICON, 'Wrong plane type'. ENDIF. ***** show attributes of all partners of travel_agency go_agency->display_attributes( ). *****DEFINITION & IMPLEMENTATION of class CL_HOTEL class CL_HOTEL definition public create public . public section. *"* public components of class CL_HOTEL *"* do not include other source files here!!! methods CONSTRUCTOR importing !IV_NAME type STRING !IV_BEDS type I . methods DISPLAY_ATTRIBUTES . class-methods DISPLAY_N_O_HOTELS . protected section. *"* protected components of class CL_HOTEL *"* do not include other source files here!!! private section. *"* private components of class CL_HOTEL *"* do not include other source files here!!! data MV_NAME type STRING . class-data GV_N_O_HOTELS type I . data MV_BEDS type I . constants C_POS_1 type I value 30. "#EC NOTEXT ENDCLASS. CLASS CL_HOTEL IMPLEMENTATION. ***** Instance Public Method CL_HOTEL->CONSTRUCTOR METHOD constructor . mv_name = iv_name. mv_beds = iv_beds. ADD 1 TO gv_n_o_hotels. ENDMETHOD. ***** Instance Public Method CL_HOTEL->DISPLAY_ATTRIBUTES METHOD display_attributes . WRITE: / 'Hotel'(001),
264
AT c_pos_1 mv_name,
© Copyright. All rights reserved.
Lesson: Creating Global Classes
/ 'Total number of beds:'(002), AT c_pos_1 mv_beds. ULINE. ULINE. SKIP. ENDMETHOD. ***** Static Public Method CL_HOTEL=>DISPLAY_N_O_HOTELS METHOD display_n_o_hotels. WRITE: / 'Total number of hotels:'(003), gv_n_o_hotels. ENDMETHOD. ENDCLASS.
© Copyright. All rights reserved.
265
Unit 6: Object-Oriented Repository Objects
LESSON SUMMARY You should now be able to:
266
●
Create global classes
●
Test global classes
●
Use global classes
© Copyright. All rights reserved.
Unit 6 Lesson 2 Defining and Implementing Global Interfaces
LESSON OVERVIEW This lesson explains how to define and implement global interfaces. Business Example As a developer, you need to create a global interface so that other developers in your organization can use the same interface and implement it in their own ways in their classes. For this reason, you require the following knowledge: ●
An understanding of how to define and implement global interfaces
●
An understanding of how to import local classes and interfaces
LESSON OBJECTIVES After completing this lesson, you will be able to: ●
Define and implement global interfaces
●
Import local classes and interfaces
Definition of Global Interfaces
Figure 114: Defining Global Interfaces
© Copyright. All rights reserved.
267
Unit 6: Object-Oriented Repository Objects
You create global interfaces like you create global classes. Right-click the program name in the Object Name screen area, and choose Create → Class. The naming convention is IF_ for SAP interfaces and ZIF_ or YIF_ for user-defined interfaces.
Implementation of Global Interfaces
Figure 115: Including Global Interfaces
If you want to include a global interface in your global class, you must enter the name of the interface on the Interfaces tab page. Once you have done that, all of the interface’s components automatically appear on the relevant tab pages according to the naming convention with the interface resolution operator. In the example, the global interface ZIF_00_PARTNER containing the method DISPLAY_PARTNER is incorporated. Double-click the method name to implement the method.
268
© Copyright. All rights reserved.
Lesson: Defining and Implementing Global Interfaces
Import of Local Classes and Interfaces
Figure 116: Importing a Local Program Class
The following procedure is an easy way to make global copies of local classes and local interfaces.
Hint: The function to copy local classes to global classes cannot be used from within OBJECT-NAVIGATOR.
To Import Local Classes and Interfaces The steps to import local classes and interfaces are as follows: 1. On the SAP Easy Access screen, choose Tools → ABAP Workbench → Development → Class Builder or call transaction SE24. 2. On the Class Builder: Initial Screen, choose Object type → Import → Local classes in program. 3. In the Import from Program dialog box, enter the name of the main program and, if the local classes and interfaces were defined within include programs, select the Explode INCLUDEs checkbox. 4. Choose the Display Classes/Interfaces button. 5. Enter names for the global classes and interfaces that you want to create. 6. Remember the customer namespace, if applicable. 7. To select all the global names, Choose the Select All button. 8. Choose the global classes and interfaces that you want to create and choose the Import button.
© Copyright. All rights reserved.
269
Unit 6: Object-Oriented Repository Objects
270
© Copyright. All rights reserved.
Unit 6 Exercise 17 Import and Implement a Global Interface
Business Example Add a hotel as a new business partner in your program for managing a travel agency’s business partners.
Note: This exercise uses the main program ZBC401_##_MAIN and the global class ZCL_##_HOTEL completed in the previous exercises. If not complete, copy the model solution from the previous exercise and the global class. In the exercises for this course, when the input values include ##, replace ## with your group number. Template SAPBC401_GCL_S1 (program) CL_HOTEL (global class) Solution SAPBC401_GCL_S2 (program) CL_HOTEL2 (global class) IF_PARTNER (global interface) Create Global Interface Create a global interface for generalized access to business partner instances. 1. If applicable, change the interface name in your UML diagram to ZIF_##_PARTNERS. (## is your two-digit group number). 2. Create the global interface ZIF_##_PARTNER. 3. Define the instance method DISPLAY_PARTNER in your global interface. If you defined the event PARTNER_CREATED in your local interface in earlier exercises, also define this event in your global interface. Hint: Instead of creating the global interface manually you can import the local interface from your program ZBC401_##_MAIN or the template program. Use the Global Interface in Your Application In the main program, replace the use of the local interface with the new global interface. 1. Completely remove the definition of the local interface.
© Copyright. All rights reserved.
271
Unit 6: Object-Oriented Repository Objects
2. Adapt all places where the local interface was used so that the global interface is used and implemented instead. Hint: Use the Find/Replace function of the ABAP Editor to reduce the typing efforts. Use the Global Interface in the Hotel Class Edit your hotel class to implement the interface, and then retest your program. 1. Ensure that your main program instantiates your own class ZCL_##_HOTEL and not the template class. 2. If necessary, add the class ZCL_##_HOTEL to your UML diagram. The class ZCL_##_HOTEL implements the interface method DISPLAY_PARTNER and triggers the instance event PARTNER_CREATED. Draw the relationships in your diagram. 3. Declare the interface as an implemented interface in your hotel class. 4. Implement the interface method in such a way that the hotel’s DISPLAY_ATTRIBUTES instance method is called. 5. Check whether the interface contains an event. If it does, ensure that it is raised in the constructor of class ZCL_##_HOTEL. 6. Save, check, and activate the global class and main program. 7. Run your program. If you have done everything correctly, the hotel attributes now appear in the list. If the hotel attributes do not appear in the list, or if an error occurs, use the ABAP Debugger to analyze the source of the error.
272
© Copyright. All rights reserved.
Unit 6 Solution 17 Import and Implement a Global Interface
Business Example Add a hotel as a new business partner in your program for managing a travel agency’s business partners.
Note: This exercise uses the main program ZBC401_##_MAIN and the global class ZCL_##_HOTEL completed in the previous exercises. If not complete, copy the model solution from the previous exercise and the global class. In the exercises for this course, when the input values include ##, replace ## with your group number. Template SAPBC401_GCL_S1 (program) CL_HOTEL (global class) Solution SAPBC401_GCL_S2 (program) CL_HOTEL2 (global class) IF_PARTNER (global interface) Create Global Interface Create a global interface for generalized access to business partner instances. 1. If applicable, change the interface name in your UML diagram to ZIF_##_PARTNERS. (## is your two-digit group number). a) Speak to your instructor if you have any questions. 2. Create the global interface ZIF_##_PARTNER. a) In transaction SE80, in the unnamed dropdown list on the left of the screen, choose Class /Interface, specify the name of the interface ZIF_##_PARTNER and press ENTER. A Create Class/Interface dialog box displays. b) To create the interface, choose Yes. A Create Interface dialog box displays. c) In the Create Interface dialog box, enter a short description for the interface and choose Save. A Create Object Directory Entry dialog box displays.
© Copyright. All rights reserved.
273
Unit 6: Object-Oriented Repository Objects
d) In the Create Object Directory Entry dialog box, enter your package name and choose Save. A Prompt for transportable Workbench request dialog box displays. e) In the Prompt for transportable Workbench request dialog box, accept the defaults and choose Continue. 3. Define the instance method DISPLAY_PARTNER in your global interface. If you defined the event PARTNER_CREATED in your local interface in earlier exercises, also define this event in your global interface. a) Choose the Methods tab. b) Enter DISPLAY_PARTNER in the Method column. c) In the Level column, use the input help to choose Instance method. d) Enter a suitable description. e) Choose the Events tab. f) In the Event column, enter PARTNER_CREATED. g) In the Level column, use the input help to choose Instance event. h) To activate the interface, choose the Activate button.
Hint: Instead of creating the global interface manually you can import the local interface from your program ZBC401_##_MAIN or the template program. Use the Global Interface in Your Application In the main program, replace the use of the local interface with the new global interface. 1. Completely remove the definition of the local interface. a) See source text excerpt from the model solution. 2. Adapt all places where the local interface was used so that the global interface is used and implemented instead. Hint: Use the Find/Replace function of the ABAP Editor to reduce the typing efforts. a) See source text excerpt from the model solution. Use the Global Interface in the Hotel Class Edit your hotel class to implement the interface, and then retest your program. 1. Ensure that your main program instantiates your own class ZCL_##_HOTEL and not the template class. a) See source text excerpt from the model solution.
274
© Copyright. All rights reserved.
Lesson: Defining and Implementing Global Interfaces
2. If necessary, add the class ZCL_##_HOTEL to your UML diagram. The class ZCL_##_HOTEL implements the interface method DISPLAY_PARTNER and triggers the instance event PARTNER_CREATED. Draw the relationships in your diagram. a) Speak to your instructor if you have any questions. 3. Declare the interface as an implemented interface in your hotel class. a) On the Interfaces tab page in your hotel class, in the Interface field, enter the name of your interface. Choose Save. 4. Implement the interface method in such a way that the hotel’s DISPLAY_ATTRIBUTES instance method is called. a) Choose the Methods tab, you will see the ZIF_##_PARTNER~DISPLAY_PARTNER METHOD. b) Double-click on the ZIF_##_PARTNER~DISPLAY_PARTNER method and enter the following code: me->DISPLAY_ATTRIBUTES( ). 5. Check whether the interface contains an event. If it does, ensure that it is raised in the constructor of class ZCL_##_HOTEL. a) At the end of the CONSTRUCTOR method, add the following code: RAISE EVENT ZIF_##_PARTNER~DISPLAY_PARTNER. 6. Save, check, and activate the global class and main program. a) Save your program. b) To check your program, on the application toolbar choose the Check button. c) To activate your program, on the application toolbar choose the Activate button. 7. Run your program. If you have done everything correctly, the hotel attributes now appear in the list. If the hotel attributes do not appear in the list, or if an error occurs, use the ABAP Debugger to analyze the source of the error. a) To run your program, on the application toolbar choose the Direct Processing button. If the list does not display the hotel attributes, or an error occurs, run the ABAP Debugger as follows: b) To activate the ABAP Debugger, choose Program → Execute → Debugging. c) Choose Execute, or press F8. The ABAP Debugger starts. Include: BC401_GCL_S2_AGENCY *------------------------------------------------* * INTERFACE lif_partners *------------------------------------------------* *INTERFACE lif_partner. * METHODS: * display_partner. * EVENTS: * partner_created. *ENDINTERFACE. "lif_partners *------------------------------------------------* * CLASS lcl_travel_agency DEFINITION *------------------------------------------------*
© Copyright. All rights reserved.
275
Unit 6: Object-Oriented Repository Objects
CLASS lcl_travel_agency DEFINITION. PUBLIC SECTION. METHODS: constructor IMPORTING iv_name TYPE string, display_agency_partners, display_attributes. PRIVATE SECTION. DATA: mv_name TYPE string, mt_partners TYPE TABLE OF REF TO if_partner. METHODS: on_partner_created FOR EVENT partner_created OF if_partner IMPORTING sender. ENDCLASS.
"lcl_travel_agency DEFINITION
*------------------------------------------------* * CLASS lcl_travel_agency IMPLEMENTATION *------------------------------------------------* CLASS lcl_travel_agency IMPLEMENTATION. METHOD display_attributes. WRITE: / icon_private_files AS ICON, 'Travel Agency:'(007), mv_name. SKIP. display_agency_partners( ). ENDMETHOD. "display_attributes METHOD display_agency_partners. DATA: lo_partner TYPE REF TO if_partner. WRITE 'Here are the partners of the travel agency:'(008). ULINE. LOOP AT mt_partners INTO lo_partner. lo_partner->display_partner( ). ENDLOOP. ENDMETHOD.
"display_agency_partners
METHOD constructor. mv_name = iv_name. SET HANDLER on_partner_created FOR ALL INSTANCES. ENDMETHOD. "constructor METHOD on_partner_created. APPEND sender TO mt_partners. ENDMETHOD. "on_partner_created ENDCLASS.
"lcl_travel_agency IMPLEMENTATION
Include: BC401_GCL_S2_CARRIER
276
© Copyright. All rights reserved.
Lesson: Defining and Implementing Global Interfaces
... *---------------------------------------------------* * CLASS lcl_carrier DEFINITION *---------------------------------------------------* CLASS lcl_carrier DEFINITION. PUBLIC SECTION. INTERFACES if_partner. METHODS: constructor IMPORTING iv_name TYPE string, on_airplane_created FOR EVENT airplane_created OF lcl_airplane IMPORTING sender, display_attributes. PRIVATE SECTION. DATA: mv_name TYPE string, mt_airplanes TYPE TABLE OF REF TO lcl_airplane. METHODS: display_airplanes. ENDCLASS.
"lcl_carrier DEFINITION
*-------------------------------------------------* * CLASS lcl_carrier IMPLEMENTATION *-------------------------------------------------* CLASS lcl_carrier IMPLEMENTATION. METHOD constructor. mv_name = iv_name. SET HANDLER on_airplane_created FOR ALL INSTANCES. RAISE EVENT if_partner~partner_created. ENDMETHOD. "constructor METHOD if_partner~display_partner. display_attributes( ). ENDMETHOD. "if_partners~display_partner METHOD on_airplane_created. APPEND sender TO mt_airplanes. ENDMETHOD. "on_airplane_created METHOD display_attributes. SKIP 2. WRITE: icon_flight AS ICON, mv_name. ULINE. ULINE. display_airplanes( ). ENDMETHOD. "display_attributes METHOD display_airplanes. DATA: lo_plane TYPE REF TO lcl_airplane. LOOP AT mt_airplanes INTO lo_plane. lo_plane->display_attributes( ). ENDLOOP. ENDMETHOD. "display_airplanes
© Copyright. All rights reserved.
277
Unit 6: Object-Oriented Repository Objects
ENDCLASS.
"lcl_carrier IMPLEMENTATION
Include: BC401_GCL_S2_RENTAL ... *---------------------------------------------------* * CLASS lcl_rental DEFINITION *---------------------------------------------------* CLASS lcl_rental DEFINITION. PUBLIC SECTION. INTERFACES: if_partner. METHODS: constructor IMPORTING iv_name TYPE string, on_vehicle_created FOR EVENT vehicle_created OF lcl_vehicle IMPORTING sender, display_attributes. PRIVATE SECTION. DATA: mv_name TYPE string, mt_vehicles TYPE TABLE OF REF TO lcl_vehicle. ENDCLASS. "lcl_rental DEFINITION *---------------------------------------------------* * CLASS lcl_rental IMPLEMENTATION *---------------------------------------------------* CLASS lcl_rental IMPLEMENTATION. METHOD if_partner~display_partner. display_attributes( ). ENDMETHOD. "if_partners~display_partner METHOD constructor. mv_name = iv_name. SET HANDLER on_vehicle_created FOR ALL INSTANCES. RAISE EVENT if_partner~partner_created. ENDMETHOD. "constructor METHOD on_vehicle_created. APPEND sender TO mt_vehicles. ENDMETHOD. "on_vehicle_created METHOD display_attributes. DATA: lo_vehicle TYPE REF TO lcl_vehicle. WRITE: / icon_transport_proposal AS ICON, mv_name. WRITE: / 'Here comes the vehicle list: '. ULINE. ULINE. LOOP AT mt_vehicles INTO lo_vehicle. lo_vehicle->display_attributes( ). ENDLOOP. ENDMETHOD. "display_attributes ENDCLASS.
278
"lcl_rental IMPLEMENTATION
© Copyright. All rights reserved.
Lesson: Defining and Implementing Global Interfaces
Global Class Program: CL_HOTEL2 class CL_HOTEL2 definition public create public . public section. *"* public components of class CL_HOTEL2 *"* do not include other source files here!!! interfaces IF_PARTNER . methods CONSTRUCTOR importing !IV_NAME type STRING !IV_BEDS type I . methods DISPLAY_ATTRIBUTES . class-methods DISPLAY_N_O_HOTELS . protected section. *"* protected components of class CL_HOTEL2 *"* do not include other source files here!!! private section. *"* private components of class CL_HOTEL2 *"* do not include other source files here!!! data MV_NAME type STRING . class-data GV_N_O_HOTELS type I . data MV_BEDS type I . constants C_POS_1 type I value 30. "#EC NOTEXT ENDCLASS.
CLASS CL_HOTEL2 IMPLEMENTATION. ***** Instance Public Method CL_HOTEL2->CONSTRUCTOR METHOD constructor . mv_name = iv_name. mv_beds = iv_beds. ADD 1 TO gv_n_o_hotels. RAISE EVENT if_partner~partner_created. ENDMETHOD. ***** Instance Public Method CL_HOTEL2->DISPLAY_ATTRIBUTES METHOD display_attribute . ULINE. WRITE: / 'Hotel'(001), AT c_pos_1 mv_name, / 'Total number of beds:'(002), AT c_pos_1 mv_beds. ULINE. ULINE. SKIP. ENDMETHOD. ***** Static Public Method CL_HOTEL2=>DISPLAY_N_O_HOTELS WRITE: / 'Total number of hotels:'(003), gv_n_o_hotels. ENDMETHOD.
© Copyright. All rights reserved.
279
Unit 6: Object-Oriented Repository Objects
***** Instance Public Method CL_HOTEL2->IF_PARTNER~DISPLAY_PARTNER METHOD if_partner~display_partner. me->display_attributes( ). ENDMETHOD. ENDCLASS.
280
© Copyright. All rights reserved.
Lesson: Defining and Implementing Global Interfaces
LESSON SUMMARY You should now be able to: ●
Define and implement global interfaces
●
Import local classes and interfaces
© Copyright. All rights reserved.
281
Unit 6 Lesson 3 Implementing Inheritance in Global Classes
LESSON OVERVIEW This lesson explains how to generate UML diagrams using inheritance in global classes. Business Example As a developer, you need to generate UML diagrams which help you to keep an overview over your global classes and their relationships to each other. Additionally, you need to improve the implementation of your hotel class by using inheritance. For this reason, you require the following knowledge: ●
An understanding of how to generate UML diagrams
●
An understanding of how to handle global classes
●
An understanding of how to use refactoring assistant
LESSON OBJECTIVES After completing this lesson, you will be able to:
282
●
Generate UML diagrams for global classes
●
Implement inheritance in global classes
●
Change the display of components in global classes
© Copyright. All rights reserved.
Lesson: Implementing Inheritance in Global Classes
Generation of UML Diagrams for Global Classes
Figure 117: Generate a UML Diagram for Package
In SAP NetWeaver 7.0 Enhancement Package 2 (EhP2), the Class Builder can generate UML diagrams for existing coding. This function will display global classes if you select a package to display. If however, you select a program, local classes and global interfaces will be displayed, but not the global classes. However, the diagrams can include objects from ABAP Dictionary. The figure shows how to start the functionality for a complete package. In a dialog box, you can add a selection of objects and specify which details you want to see on the diagram.
© Copyright. All rights reserved.
283
Unit 6: Object-Oriented Repository Objects
Inheritance in Global Classes
Figure 118: Defining an Inheritance Relationship
Set out the inheritance relationships between global classes on the Properties tab page. Choose the Superclass button to specify a superclass. In the example shown in the figure Defining an Inheritance Relationship,, the subclass ZCL_CARGO_PLANE_00 inherits from superclass ZCL_AIRPLANE_00.
Redefinition of a Method in Global Class
Figure 119: Redefining an Inherited Method
284
© Copyright. All rights reserved.
Lesson: Implementing Inheritance in Global Classes
To redefine an inherited method, select the relevant method in the list and choose the Redefine button. Alternatively, you can use the context menu in the navigation area.
Note: The appearance of some of the buttons or menus depends on the release level. The button for redefining methods is one example.
Hint: To define the constructor in the subclass, choose the CONSTRUCTOR button in the application toolbar. The system then proposes transferring the signature of the superclass constructor. This is helpful when you want to create the subclass constructor. You can add some parameters here. Similarly, you can find the call for the superclass here.
Local Types in Global Classes
Figure 120: Defining a Local Type
You can define local types in global classes. Global classes includes local classes. Technically, you are not defining a class within a class, but a class that is local in the repository object of the global class. All components of the global class have access to these local types, but they are encapsulated if you try to access them from outside. The same applies for local interfaces in global classes. To edit the implementation parts of these local classes, choose the Impl button.
© Copyright. All rights reserved.
285
Unit 6: Object-Oriented Repository Objects
Class Component Display
Figure 121: Structured Display of Inherited Components
To improve your understanding of inheritance and interface components, you can set the Group by Classes and Interfaces flag in the User-Specific Settings for the Class Builder. The system will then display the components of the global class in a group. Sorting the Component Display of Global Classes
Figure 122: Sorting the Component Display of Global Classes
You can sort all components by five criteria in three levels. Choose the Sort pushbutton to display the appropriate dialog box. LESSON SUMMARY You should now be able to: ●
286
Generate UML diagrams for global classes
© Copyright. All rights reserved.
Lesson: Implementing Inheritance in Global Classes
●
Implement inheritance in global classes
●
Change the display of components in global classes
© Copyright. All rights reserved.
287
Unit 6: Object-Oriented Repository Objects
288
© Copyright. All rights reserved.
Unit 6 Learning Assessment
1. You can only use local classes or interfaces within the same program in which they are defined and implemented. Determine whether this statement is true or false. X
True
X
False
2. The naming convention for SAP Standard Global Interfaces is ZIF_ or YIF_. Determine whether this statement is true or false. X
True
X
False
3. Which of the following buttons in Class Builder is used to override an inherited method? Choose the correct answer. X
A CONSTRUCTOR
X
B Redefine
X
C Implementation
4. Local types of the global class are encapsulated and cannot be accessed from outside. Determine whether this statement is true or false. X
True
X
False
© Copyright. All rights reserved.
289
Unit 6 Learning Assessment - Answers
1. You can only use local classes or interfaces within the same program in which they are defined and implemented. Determine whether this statement is true or false. X
True
X
False
2. The naming convention for SAP Standard Global Interfaces is ZIF_ or YIF_. Determine whether this statement is true or false. X
True
X
False
3. Which of the following buttons in Class Builder is used to override an inherited method? Choose the correct answer. X
A CONSTRUCTOR
X
B Redefine
X
C Implementation
4. Local types of the global class are encapsulated and cannot be accessed from outside. Determine whether this statement is true or false.
290
X
True
X
False
© Copyright. All rights reserved.
UNIT 7
ABAP Object-Oriented Examples
Lesson 1 Using the ABAP List Viewer (ALV) Exercise 18: Implement the ALV Grid Control Exercise 19: Implement a Dialog Box with the ALV Grid Control
292 299 305
Lesson 2 Describing Business Add-Ins (BAdIs)
314
UNIT OBJECTIVES ●
Implement a simple ALV grid
●
Handle the double-click event of the ALV grid
●
Describe BAdls
© Copyright. All rights reserved.
291
Unit 7 Lesson 1 Using the ABAP List Viewer (ALV)
LESSON OVERVIEW This lesson shows you how to implement ABAP List Viewer (ALV). Business Example You need to create a report using the ALV Grid Control. For this reason, you require the following knowledge: ●
An understanding of the ALV Grid Control
●
An understanding of usage of an ALV in a screen area
●
An understanding of how to implement ALV
●
An understanding of implementation of a handler for the double-click event
●
An understanding of how to implement an event handler for the ALV Grid Control
●
An understanding of how to implement a popup with the ALV Grid Control
LESSON OBJECTIVES After completing this lesson, you will be able to:
292
●
Implement a simple ALV grid
●
Handle the double-click event of the ALV grid
© Copyright. All rights reserved.
Lesson: Using the ABAP List Viewer (ALV)
The ALV Grid Control
Figure 123: The ALV Grid Control
The following topics illustrate the possible application areas of object-oriented ABAP programming and the use of SAP standard classes. For example, ALV Grid Control in the context of the Control Framework and the Business Add-Ins (BAdIs). The SAP Control Framework is a collection of global classes and interfaces that you can use to add SAP GUI controls in your ABAP Objects programs, regardless of the platform. The ALV Grid Control is a tool that you can use to display non-hierarchical lists in a standardized form. The list data displays in tables. It is easy to work with the tool, as there are very few programming steps that must be carried out. The ALV Grid Control contains a number of interactive standard functions that users of lists often need, for example, print, export. As a developer, you have the option of hiding these standard functions. When required, you can adapt the implementations to fit the needs of your application. You can also add your own functions to the application toolbar.
© Copyright. All rights reserved.
293
Unit 7: ABAP Object-Oriented Examples
Including an ALV Grid Control Instance in a Dialog Program
Figure 124: Including an ALV Grid Control Instance in a Dialog Program
Container Controls provide the technical connection between the screen and application controls. The application controls ALV Grid Control, Tree Control, and Picture Control are always embedded in the Container Control, which is connected to the screen. There are different types of container controls. However, all incorporate fundamental control functions, such as scroll bars.
Creation of an ALV
Figure 125: Displaying Application Data Using an ALV Grid Instance
You must place an ALV Grid Control in a screen area with a fixed size. To do this, you must create an instance of each of the global classes CL_GUI_CUSTOM_CONTAINER and CL_GUI_ALV_GRID.
294
© Copyright. All rights reserved.
Lesson: Using the ABAP List Viewer (ALV)
For normal display, perform the following programming steps: 1. Use the full screen editor of the Screen Painter to define a custom control area on your screen. 2. Create an instance of the class CL_GUI_CUSTOM_CONTAINER and transfer the name of the custom control area to the constructor. 3. Create an instance of the class CL_GUI_GUI_ALV_GRID and transfer the reference to the custom control instance to the constructor. 4. Call the method SET_TABLE_FOR_FIRST_DISPLAY of the grid control instance and transfer the internal standard table to it, which contains the data to be displayed. If the table has a global row type defined in ABAP Dictionary, you can transfer the name of this global structure to the same method. The ALV Grid Control then automatically creates the field catalog.
Caution: The internal table transferred to the method SET_TABLE_FOR_FIRST_DISPLAY must be globally defined. Therefore, the table must be either a global program variable or a public attribute of a class. When you change the contents of the internal tables while the program is running, you only need to call the method REFRESH_TABLE_DISPLAY in the relevant dialog step to refresh the display.
Implementation of a Handler for the Double-Click Event
Figure 126: ALV Grid Control – Double-Click
An ALV Grid Control can react to the user’s double-click. As a possible reaction, you can trigger a follow-on processing step in which additional information is displayed.
© Copyright. All rights reserved.
295
Unit 7: ABAP Object-Oriented Examples
In the example shown in the figure ALV Grid Control – Double-Click, the booking data for the individual flight customers or data on the aircraft, can also be displayed for the flight data. This is executed by catching the event DOUBLE_CLICK with a handler method. ALV Grid Control – Reacting to a Double-Click
Figure 127: ALV Grid Control – Reacting to a Double-Click
A handler method is a class method (static method) or an instance method of an object. If a class method is defined as a handler method, no object of the handled class needs to be instantiated to use the method. To create a handler object for an event, define a class. This class has a public method in the public section that can react to an event. During the implementation of the handler method, define the source text that must be run when the event is triggered. The method receives the information that the event delivers from the mouse position when you double-click, and creates an information message in the control example that displays the row and field of the mouse click.
296
© Copyright. All rights reserved.
Lesson: Using the ABAP List Viewer (ALV)
Note: Extensive documentation about the SAP Control Framework is available in the standard SAP product documentation (delivered with the product or online through the SAP Help portal). The SAP Library contains comprehensive descriptions of all classes and a complete tutorial. The ABAP Workbench Object Navigator also contains the Demo Center, which makes it very easy to use standard template programs. To find the ABAP Workbench Object Navigator, choose Environment → Examples → Controls Examples. Individual elements of the SAP Control Framework are covered in other courses. SAP also offers a separate comprehensive course about dialog programming with the SAP controls. The course covers all aspects, including complex programming techniques such as the drag and drop functions.
© Copyright. All rights reserved.
297
Unit 7: ABAP Object-Oriented Examples
298
© Copyright. All rights reserved.
Unit 7 Exercise 18 Implement the ALV Grid Control
Business Example You want to see a list of flight connections in an ALV Grid Control. When you double-click a connection, the selected row number and column name must display. Template: SAPBC401_ALV_T1 Solution: SAPBC401_ALV_S1 Create an ALV Grid Control, and react to double-click on the ALV Grid Control. Programming an ALV Grid Control Programming an ALV Grid Control and displaying the list of flight connections already stored in internal table GT_SPFLI. 1. Copy the template program SAPBC401_ALV_T1 to ZBC401_##_ALV. 2. In the main program, define the reference variables GO_CONTAINER and GO_ALV_GRID required for the ALV Grid Control. 3. Analyze the existing screen 100, paying particular attention to the name of the Custom Container Control Area, which is used as the basis for the ALV Grid Control. Implement the PBO module ALV_GRID. Use the reference variables to instantiate the two classes in this PBO module. Pay attention to the fact that the CREATE OBJECT is not called repeatedly when the PBO is executed repeatedly. 4. To display data in the ALV Grid Control, call the method SET_TABLE_FOR_FIRST_DISPLAY and transfer the internal table with the flight connection data and the name of the line type of that internal table. 5. Activate and test your program. Caution: You are working with a screen in this exercise, so always activate all parts of the program as well as the screen.
Handle a Double-Click Handle a double-click on the ALV Grid Control. If the user double-clicks a row in the ALV Grid Control, the row number and column name where the user double-clicked should be displayed in a message of type I.
© Copyright. All rights reserved.
299
Unit 7: ABAP Object-Oriented Examples
1. Define a local class LCL_EVENT_HANDLER, and in this class, define an instance method to handle the event DOUBLE_CLICK that the ALV Grid Control triggered. Note: The class LCL_EVENT_HANDLER only acts as a handler and, otherwise, does not have any other functions. Import parameters ES_ROW_NO and E_COLUMN into the handler method. 2. Implement the handler method. Send a message of type I to output the row number and column name the user clicked. 3. Create the handler instance and register the handler method CREATE OBJECT GO_HANDLER. 4. Activate and test your program.
300
© Copyright. All rights reserved.
Unit 7 Solution 18 Implement the ALV Grid Control
Business Example You want to see a list of flight connections in an ALV Grid Control. When you double-click a connection, the selected row number and column name must display. Template: SAPBC401_ALV_T1 Solution: SAPBC401_ALV_S1 Create an ALV Grid Control, and react to double-click on the ALV Grid Control. Programming an ALV Grid Control Programming an ALV Grid Control and displaying the list of flight connections already stored in internal table GT_SPFLI. 1. Copy the template program SAPBC401_ALV_T1 to ZBC401_##_ALV. a) Carry out this step in the usual manner. 2. In the main program, define the reference variables GO_CONTAINER and GO_ALV_GRID required for the ALV Grid Control. a) Review the source code extract from the model solution or refer to the corresponding slides about the ALV Grid Control. 3. Analyze the existing screen 100, paying particular attention to the name of the Custom Container Control Area, which is used as the basis for the ALV Grid Control. Implement the PBO module ALV_GRID. Use the reference variables to instantiate the two classes in this PBO module. Pay attention to the fact that the CREATE OBJECT is not called repeatedly when the PBO is executed repeatedly. a) Review the source code extract from the model solution, or refer to the corresponding slides about the ALV Grid Control. Speak to your instructor if you have any questions. 4. To display data in the ALV Grid Control, call the method SET_TABLE_FOR_FIRST_DISPLAY and transfer the internal table with the flight connection data and the name of the line type of that internal table. a) Review the source code extract from the model solution, or refer to the corresponding slides about the ALV Grid Control. Speak to your instructor if you have any questions. 5. Activate and test your program. Caution: You are working with a screen in this exercise, so always activate all parts of the program as well as the screen.
© Copyright. All rights reserved.
301
Unit 7: ABAP Object-Oriented Examples
a) Save your program. b) To check your program, on the application toolbar choose the Check button. c) To activate your program, on the application toolbar choose the Activate button. d) To run your program, on the application toolbar choose the Direct Processing button.
Handle a Double-Click Handle a double-click on the ALV Grid Control. If the user double-clicks a row in the ALV Grid Control, the row number and column name where the user double-clicked should be displayed in a message of type I. 1. Define a local class LCL_EVENT_HANDLER, and in this class, define an instance method to handle the event DOUBLE_CLICK that the ALV Grid Control triggered. Note: The class LCL_EVENT_HANDLER only acts as a handler and, otherwise, does not have any other functions. Import parameters ES_ROW_NO and E_COLUMN into the handler method. a) See the source code extract from the model solution. 2. Implement the handler method. Send a message of type I to output the row number and column name the user clicked. a) In the ON_DOUBLE_CLICK method of class LCL_EVENT_HANDLER enter the following code: MESSAGE i010(bc401) WITH es_row_no-row_id e_column-fieldname 3. Create the handler instance and register the handler method CREATE OBJECT GO_HANDLER. a) Between instantiating the class CL_GUI_ALV_GRID and calling the method SET_TABLE_FOR_FIRST_DISPLAY enter the following code: SET HANDLER go_handler->on_double_click FOR go_alv_grid. 4. Activate and test your program. a) Save your program. b) To check your program, on the application toolbar choose the Check button. c) To activate your program, on the application toolbar choose the Activate button. d) To run your program, on the application toolbar choose the Direct Processing button. e) Carry out this step in the usual manner. Make sure that the program displays as follows: SAPBC401_ALV_S1 REPORT
sapbc401_alv_s1.
*-------------------------------------------------*
302
© Copyright. All rights reserved.
Lesson: Using the ABAP List Viewer (ALV)
* CLASS lcl_event_handler DEFINITION *-------------------------------------------------* CLASS lcl_event_handler DEFINITION. PUBLIC SECTION. METHODS on_double_click FOR EVENT double_click OF cl_gui_alv_grid IMPORTING es_row_no e_column. ENDCLASS. "lcl_event_handler DEFINITION *-------------------------------------------------* * CLASS lcl_event_handler IMPLEMENTATION *-------------------------------------------------* CLASS lcl_event_handler IMPLEMENTATION. METHOD on_double_click. MESSAGE i010(bc401) WITH es_row_no-row_id e_column-fieldname. ENDMETHOD. ENDCLASS.
"handler_method "lcl_event_handler IMPLEMENTATION
*** Types and Data Definitions TYPES: ty_spfli TYPE STANDARD TABLE OF spfli WITH NON-UNIQUE KEY carrid connid. DATA: ok_code TYPE sy-ucomm. DATA: go_handler TYPE REF TO lcl_event_handler, go_container TYPE REF TO cl_gui_custom_container, go_alv_grid TYPE REF TO cl_gui_alv_grid. DATA: gt_spfli TYPE ty_spfli.
START-OF-SELECTION. ******************** SELECT * FROM spfli INTO TABLE gt_spfli. CALL SCREEN '0100'. *&----------------------------------------------* *& Module STATUS_0100 OUTPUT *&----------------------------------------------* MODULE status_0100 OUTPUT. SET PF-STATUS 'DYNPROSTATUS'. SET TITLEBAR 'TITLE1'. ENDMODULE. " STATUS_0100 OUTPUT *&----------------------------------------------* *& Module ALV_GRID OUTPUT *&----------------------------------------------* MODULE alv_grid OUTPUT. ** Create object of class CL_GUI_CUSTOM_CONTAINER ** to manage data IF go_container IS NOT BOUND.
© Copyright. All rights reserved.
303
Unit 7: ABAP Object-Oriented Examples
CREATE OBJECT go_container EXPORTING container_name = 'CONTAINER_1' EXCEPTIONS others = 6. IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ENDIF. ** create object of class cl_gui_alv_grid to visualize data CREATE OBJECT go_alv_grid EXPORTING i_parent = go_container EXCEPTIONS others = 5. IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ENDIF. ** create handler instance and register handler method CREATE OBJECT go_handler. SET HANDLER go_handler->on_double_click FOR go_alv_grid. ** Call method to visualize data of internal table CALL METHOD go_alv_grid->set_table_for_first_display EXPORTING i_structure_name = 'SPFLI' CHANGING it_outtab = gt_spfli EXCEPTIONS OTHERS = 4. IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ENDIF. ENDIF. ENDMODULE.
" ALV_GRID
OUTPUT
*&-----------------------------------------------* *& Module USER_COMMAND_0100 INPUT *&-----------------------------------------------* MODULE user_command_0100 INPUT. CASE ok_code. WHEN 'BACK'. SET SCREEN 0. WHEN 'EXIT'. LEAVE PROGRAM. ENDCASE. ENDMODULE.
304
" USER_COMMAND_0100
INPUT
© Copyright. All rights reserved.
Unit 7 Exercise 19 Implement a Dialog Box with the ALV Grid Control
Business Example You need to see a list of flight connections in an ALV Grid Control. When you double-click one connection, the list of flights for this connection must be displayed in a second ALV Grid Control. Template: SAPBC401_ALV_S1 Solution: SAPBC401_ALV_S2 Read from a Database Table Read from the database table SFLIGHT about the flights that belong to the flight connection that you double-clicked. 1. Complete your program ZBC401_##_ALV (where ## is your two-digit group number) or copy the model solution from the previous exercise. 2. In the event handler method, remove the MESSAGE statement. Define a local structure (suggested name - LS_SPFLI) to serve as a work area for internal table GT_SPFLI. From GT_SPFLI, read the entry that corresponds to the grid row you double-clicked. Hint: Use READ TABLE with an index access.
3. Is defining GT_SPFLI after the definition of the event handler class acceptable?
4. In the definition of the event handler class, define a private instance attribute MT_SFLIGHT, which is an internal (standard) table with line type SFLIGHT. Hint: Define a private table type TY_SFLIGHT in the same class.
© Copyright. All rights reserved.
305
Unit 7: ABAP Object-Oriented Examples
5. In the event handler method, implement an array fetch for database table SFLIGHT to fill MT_SFLIGHT with those flights that have the same key fields as the flight connection that you have clicked. 6. Activate your program and analyze it in the ABAP Debugger. Make sure MT_SFLIGHT is filled correctly.
Extend the Event Handler Method Extend your event handler method so that the selected flights are presented in a second ALV Grid Control which is displayed in a dialog box. 1. In your event handler class, define two reference variables as private instance attributes (suggested names – MO_CONT_POPUP and MO_ALV_POPUP). Type them with the global classes CL_GUI_DIALOGBOX_CONTAINER and CL_GUI_ALV_GRID. 2. In your event handler method, use these reference variables to create instances of the two classes. Make sure the CREATE OBJECT statement is not called repeatedly when the event handler method is executed repeatedly. 3. To display data in the ALV Grid Control, call the method SET_TABLE_FOR_FIRST_DISPLAY and transfer the internal table MT_SFLIGHT with the flight data and the name of the line type of that internal table. Make sure this method is only called if the dialog box container and the second ALV Grid Control have just been created. 4. If the dialog box container and the second ALV Grid Control already exist, do not call method SET_TABLE_FOR_FIRST_DISPLAY to refresh the data displayed. Call the method REFRESH_TABLE_DISPLAY instead. Hint: You do not have to provide values for the optional parameters of this method.
5. Activate and test your program. Note: At this point, clicking the button in the top-right corner of the window does not close the dialog box container. To implement this function, you must handle event CLOSE of class CL_GUI_DIALOGBOX_CONTAINER and call method FREE of the dialog box container. Other training courses and the Control Framework documentation explain the this procedure in detail.
306
© Copyright. All rights reserved.
Unit 7 Solution 19 Implement a Dialog Box with the ALV Grid Control
Business Example You need to see a list of flight connections in an ALV Grid Control. When you double-click one connection, the list of flights for this connection must be displayed in a second ALV Grid Control. Template: SAPBC401_ALV_S1 Solution: SAPBC401_ALV_S2 Read from a Database Table Read from the database table SFLIGHT about the flights that belong to the flight connection that you double-clicked. 1. Complete your program ZBC401_##_ALV (where ## is your two-digit group number) or copy the model solution from the previous exercise. a) Carry out this step in the usual manner. 2. In the event handler method, remove the MESSAGE statement. Define a local structure (suggested name - LS_SPFLI) to serve as a work area for internal table GT_SPFLI. From GT_SPFLI, read the entry that corresponds to the grid row you double-clicked. Hint: Use READ TABLE with an index access.
a) See the source code extract from the model solution. 3. Is defining GT_SPFLI after the definition of the event handler class acceptable? No. To be able to access the global data object GT_SPFLI from within the local class implementation, the data object must be defined as global program variable before the local class definition. 4. In the definition of the event handler class, define a private instance attribute MT_SFLIGHT, which is an internal (standard) table with line type SFLIGHT.
© Copyright. All rights reserved.
307
Unit 7: ABAP Object-Oriented Examples
Hint: Define a private table type TY_SFLIGHT in the same class.
a) See the source code extract from the model solution. 5. In the event handler method, implement an array fetch for database table SFLIGHT to fill MT_SFLIGHT with those flights that have the same key fields as the flight connection that you have clicked. a) See the source code extract from the model solution. 6. Activate your program and analyze it in the ABAP Debugger. Make sure MT_SFLIGHT is filled correctly. a) Carry out this step in the usual manner.
Extend the Event Handler Method Extend your event handler method so that the selected flights are presented in a second ALV Grid Control which is displayed in a dialog box. 1. In your event handler class, define two reference variables as private instance attributes (suggested names – MO_CONT_POPUP and MO_ALV_POPUP). Type them with the global classes CL_GUI_DIALOGBOX_CONTAINER and CL_GUI_ALV_GRID. a) See the source code extract from the model solution. 2. In your event handler method, use these reference variables to create instances of the two classes. Make sure the CREATE OBJECT statement is not called repeatedly when the event handler method is executed repeatedly. a) See the source code extract from the model solution. 3. To display data in the ALV Grid Control, call the method SET_TABLE_FOR_FIRST_DISPLAY and transfer the internal table MT_SFLIGHT with the flight data and the name of the line type of that internal table. Make sure this method is only called if the dialog box container and the second ALV Grid Control have just been created. a) See the source code extract from the model solution. 4. If the dialog box container and the second ALV Grid Control already exist, do not call method SET_TABLE_FOR_FIRST_DISPLAY to refresh the data displayed. Call the method REFRESH_TABLE_DISPLAY instead. Hint: You do not have to provide values for the optional parameters of this method.
a) See the source code extract from the model solution. 5. Activate and test your program.
308
© Copyright. All rights reserved.
Lesson: Using the ABAP List Viewer (ALV)
Note: At this point, clicking the button in the top-right corner of the window does not close the dialog box container. To implement this function, you must handle event CLOSE of class CL_GUI_DIALOGBOX_CONTAINER and call method FREE of the dialog box container. Other training courses and the Control Framework documentation explain the this procedure in detail. a) Carry out this step in the usual manner. SAPBC401_ALV_S2 REPORT
sapbc401_alv_s2.
TYPES: ty_spfli TYPE STANDARD TABLE OF spfli WITH NON-UNIQUE KEY carrid connid. DATA: gt_spfli TYPE ty_spfli. *--------------------------------------------------* * CLASS lcl_event_handler DEFINITION *--------------------------------------------------* * *--------------------------------------------------* CLASS lcl_event_handler DEFINITION. PUBLIC SECTION. METHODS on_double_click FOR EVENT double_click OF cl_gui_alv_grid IMPORTING es_row_no e_column. PRIVATE SECTION. TYPES: ty_sflight TYPE STANDARD TABLE OF sflight WITH NON-UNIQUE KEY carrid connid fldate. DATA: mo_cont_popup TYPE REF TO cl_gui_dialogbox_container, mo_alv_popup TYPE REF TO cl_gui_alv_grid. DATA: mt_sflight TYPE ty_sflight. ENDCLASS.
"lcl_event_handler DEFINITION
*--------------------------------------------------* * CLASS lcl_event_handler IMPLEMENTATION *--------------------------------------------------* * *--------------------------------------------------* CLASS lcl_event_handler IMPLEMENTATION. METHOD on_double_click. DATA ls_spfli TYPE spfli. READ TABLE gt_spfli INTO ls_spfli INDEX es_row_no-row_id. SELECT * FROM sflight INTO TABLE mt_sflight
© Copyright. All rights reserved.
309
Unit 7: ABAP Object-Oriented Examples
WHERE carrid = ls_spfli-carrid AND connid = ls_spfli-connid. IF mo_cont_popup IS NOT BOUND. CREATE OBJECT mo_cont_popup EXPORTING width = 600 height = 300 EXCEPTIONS others = 8. IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ENDIF. CREATE OBJECT mo_alv_popup EXPORTING i_parent = mo_cont_popup EXCEPTIONS others = 5. IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ENDIF. mo_alv_popup->set_table_for_first_display( EXPORTING i_structure_name = 'SFLIGHT' CHANGING it_outtab = mt_sflight EXCEPTIONS OTHERS = 4 ). IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ENDIF. ELSE. mo_alv_popup->refresh_table_display( EXCEPTIONS OTHERS = 2 ). IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ENDIF. ENDIF. * MESSAGE i010(bc401) WITH * es_row_no-row_id e_column-fieldname. ENDMETHOD. ENDCLASS.
"handler_method "lcl_event_handler IMPLEMENTATION
DATA: ok_code TYPE sy-ucomm. DATA: go_handler TYPE REF TO lcl_event_handler,
310
© Copyright. All rights reserved.
Lesson: Using the ABAP List Viewer (ALV)
go_container TYPE REF TO cl_gui_custom_container, go_alv_grid TYPE REF TO cl_gui_alv_grid. START-OF-SELECTION. ******************** SELECT * FROM spfli INTO TABLE gt_spfli. CALL SCREEN '0100'. *&------------------------------------------------* *& Module STATUS_0100 OUTPUT *&------------------------------------------------* * text *-------------------------------------------------* MODULE status_0100 OUTPUT. SET PF-STATUS 'DYNPROSTATUS'. SET TITLEBAR 'TITLE1'. ENDMODULE. " STATUS_0100 OUTPUT *&------------------------------------------------* *& Module ALV_GRID OUTPUT *&------------------------------------------------* * text *-------------------------------------------------* MODULE alv_grid OUTPUT. * Create object of class CL_GUI_CUSTOM_CONTAINER to * manage data IF go_container IS NOT BOUND. CREATE OBJECT go_container EXPORTING container_name = 'CONTAINER_1' EXCEPTIONS others = 6. IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ENDIF. * create object of class cl_gui_alv_grid to visualize data CREATE OBJECT go_alv_grid EXPORTING i_parent = go_container EXCEPTIONS others = 5. IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ENDIF. ** create handler Instance CREATE OBJECT go_handler. ** set handler to react on double-click SET HANDLER go_handler->on_double_click FOR go_alv_grid. ** Call method to visualize data of internal table CALL METHOD go_alv_grid->set_table_for_first_display EXPORTING
© Copyright. All rights reserved.
311
Unit 7: ABAP Object-Oriented Examples
i_structure_name = 'SPFLI' CHANGING it_outtab = gt_spfli EXCEPTIONS OTHERS = 4. IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. ENDIF. ENDIF. ENDMODULE.
" ALV_GRID
OUTPUT
*&-------------------------------------------------* *& Module USER_COMMAND_0100 INPUT *&-------------------------------------------------* MODULE user_command_0100 INPUT. CASE ok_code. WHEN 'BACK'. SET SCREEN 0. WHEN 'EXIT'. LEAVE PROGRAM. ENDCASE. ENDMODULE.
312
" USER_COMMAND_0100
INPUT
© Copyright. All rights reserved.
Lesson: Using the ABAP List Viewer (ALV)
LESSON SUMMARY You should now be able to: ●
Implement a simple ALV grid
●
Handle the double-click event of the ALV grid
© Copyright. All rights reserved.
313
Unit 7 Lesson 2 Describing Business Add-Ins (BAdIs)
LESSON OVERVIEW This lesson shows you how to implement Business Add-Ins (BAdIs). Business Example You need to enhance functionality in an SAP standard program, without altering the original program. This can be done by using BAdIs. For this reason, you require the following knowledge: ●
An understanding of BAdIs
●
An understanding of how to define a BAdI
●
An understanding of how to implement a BAdI
LESSON OBJECTIVES After completing this lesson, you will be able to: ●
Describe BAdls
BAdIs Unlike Customer Exits, BAdIs are optimized for the changed software delivery process. The typical software delivery process does not only consist of providers and customers, rather several intermediate providers may be involved in the delivery chain for software. For example, an SAP partner can extend an SAP application program with an industry solution like Industrial Business Unit (IBU). The customer can then again extend the same program.
314
© Copyright. All rights reserved.
Lesson: Describing Business Add-Ins (BAdIs)
BAdI – Basics
Figure 128: BAdI – Basics
With a BAdI, an SAP application provides the enhancement option through an interface and an adapter class implementing that interface. The interface can be implemented by several users in the delivery chain, thus, multiple BAdI implementations are possible. Additionally, a BAdI implementation itself can provide another BAdI which can be implemented by users who appear further out in the delivery chain. Definition of a BAdI – Basics
Figure 129: Definition of a BAdI – Basics
When you define a BAdI, you must specify an interface (IF_EX_) with corresponding formally defined methods. The adapter class that is automatically generated during the
© Copyright. All rights reserved.
315
Unit 7: ABAP Object-Oriented Examples
interface definition (CL_EX_) has, among other capabilities, the function of calling all active implementations of the BAdI. When you have several active implementations, there is no predefined processing sequence. To Define a BAdI 1. Run the transaction SE18 or on the SAP Easy Access screen, choose Tools → ABAP Workbench → Utilities → Business Add-Ins → Definition. 2. As of SAP Netweaver 7.0 you cannot directly create a BAdI. First, you must create an Enhancement Spot. Enter the Enhancement Spot name and choose the Create button. A Create Enhancement Spot dialog displays. 3. In the Create Enhancement Spot dialog, enter a short description, and choose the Creation of an Enhancement button. Save the enhancement to your package. 4. Choose the Create Badi button. A Create BAdI Definition dialog displays, enter a short description. Choose the Continue button. 5. In the BAdI Definition screen area, expand the node, and double-click Interface. 6. Enter your interface name ZIF_BC401_00_BADI_DEMO and press Enter. A Class/ Interface dialog displays. 7. On the Class/Interface dialog, choose Yes to create the interface. Save it to your package, then save the enhancement spot. The class builder will display on the Method tab page. 8. Enter an instance method and a description, and activate the interface.
The BAdI Calling Program
Figure 130: BAdI – The Calling Program
The figure BAdI – The Calling Program, shows an example of a BAdI call.
316
© Copyright. All rights reserved.
Lesson: Describing Business Add-Ins (BAdIs)
A reference variable for the type of BAdI must be defined. An object of the adapter class is instantiated by the call of the GET_INSTANCE static method of the CL_EXITHANDLER class. The variable gb_adapter points to this instance. The interface methods of the BAdI can be called by gb_adapter object reference.
The Search for BAdIs You can search the BAdI using the following strategies: ●
You can use the Repository Information System (transaction SE84).
●
You can use the Application Hierarchy (transaction SE81).
●
You can use the Customizing Guide (Implementation guide for transaction SPRO).
●
●
●
You can search in the application source code for the CL_EXITHANDLER=>GET_INSTANCE statement. You can search in the application source code for the occurrence of the BAdI interfaces with the naming convention IF_EX_. As of SAP Netweaver AS 7.0, you can search in the application source code for occurrences of the GET BADI statement.
The name of the BAdl must be investigated before you can implement the BAdI. When searching for BAdI names, you can use the search mechanisms. Double-click the reference variable (gb_adapter) in the example to get the interface definition. You can derive the BAdI name from the name of the interface.
Note: How to search in ABAP source code: When running an arbitrary transaction press F1 key. On the displayed dialog choose the Technical Information button. Navigate to the source code of the program by double-clicking the program name. Then call the global search function in menu Edit → Find Next and search for the desired string. Do not use the editor's search function Edit → Find/Replace (Ctrl + F) because this function will consider a single source code include only.
© Copyright. All rights reserved.
317
Unit 7: ABAP Object-Oriented Examples
BAdI Implementation
Figure 131: Implementation of a BAdI – SE19
When the name of the BAdI is determined, the BAdI can be implemented. The implementation of the BAdI is performed through the implementation maintenance under Tools → ABAP Workbench → Utilities → Business Add-Ins → Implementation (transaction code SE19). Alternatively, you can go to the implementations by navigating the menu from the BAdI definition. To implement a BAdI, a BAdI implementation name must be issued. The naming convention is Z. A dialog box then appears for selecting the corresponding BAdI. The code to be implemented is stored in a method of an automatically generated customer class. For this reason, the name of the implementing class must be given in a final dialog box. The default name from SAP is comprised of Y or Z (the namespace prefix), CL_ (for class), IM_ (for implementation), and (the actual name of the implementation). When you double-click one of the BAdI methods, you can enter the code of the method. You can also create auxiliary methods in the implementing class to better structure the required code of the BAdI method.
Note: Activate the methods or the implementations at the end of the task.
To Implement a BAdI 1. Run the transaction code SE19. 2. Enter the BAdI definition name (or Enhancement Spot name) and choose the Create button.
318
© Copyright. All rights reserved.
Lesson: Describing Business Add-Ins (BAdIs)
3. Enter an implementation name and choose the OK button. 4. Enter a description text and choose the Save button. 5. Double-click the name of the implementing class to navigate to the class and implement your source code there. LESSON SUMMARY You should now be able to: ●
Describe BAdls
© Copyright. All rights reserved.
319
Unit 7: ABAP Object-Oriented Examples
320
© Copyright. All rights reserved.
Unit 7 Learning Assessment
1. The ABAP List Viewer (ALV) Grid Control is a tool that you can use to display nonhierarchical lists in a standardized form. Determine whether this statement is true or false. X
True
X
False
2. Container controls provide the technical connection between the screen and the application control. Determine whether this statement is true or false. X
True
X
False
3. To create a handler object for an event, we must first define a ____________. Choose the correct answer. X
A class
X
B structure
X
C screen
X
D attribute
4. A handler method can be either a class method (static method) or an instance method of an object. Determine whether this statement is true or false. X
True
X
False
© Copyright. All rights reserved.
321
Unit 7: Learning Assessment
5. With a Business Add-In (BAdI), an SAP application program provides the enhancement option through an interface method. Determine whether this statement is true or false. X
True
X
False
6. An object of the BAdI adapter class is instantiated by the call of the static method GET_INSTANCE of the class CL_EXITHANDLER. Determine whether this statement is true or false. X
True
X
False
7. To implement a Business Add-In (BAdI), the BADI definition name must be determined. Determine whether this statement is true or false. X
True
X
False
8. The code of a BAdI implementation is stored in a __________ of an automatically generated customer class. Choose the correct answer.
322
X
A method
X
B structure
X
C object
© Copyright. All rights reserved.
Unit 7 Learning Assessment - Answers
1. The ABAP List Viewer (ALV) Grid Control is a tool that you can use to display nonhierarchical lists in a standardized form. Determine whether this statement is true or false. X
True
X
False
2. Container controls provide the technical connection between the screen and the application control. Determine whether this statement is true or false. X
True
X
False
3. To create a handler object for an event, we must first define a ____________. Choose the correct answer. X
A class
X
B structure
X
C screen
X
D attribute
4. A handler method can be either a class method (static method) or an instance method of an object. Determine whether this statement is true or false. X
True
X
False
© Copyright. All rights reserved.
323
Unit 7: Learning Assessment - Answers
5. With a Business Add-In (BAdI), an SAP application program provides the enhancement option through an interface method. Determine whether this statement is true or false. X
True
X
False
6. An object of the BAdI adapter class is instantiated by the call of the static method GET_INSTANCE of the class CL_EXITHANDLER. Determine whether this statement is true or false. X
True
X
False
7. To implement a Business Add-In (BAdI), the BADI definition name must be determined. Determine whether this statement is true or false. X
True
X
False
8. The code of a BAdI implementation is stored in a __________ of an automatically generated customer class. Choose the correct answer.
324
X
A method
X
B structure
X
C object
© Copyright. All rights reserved.
UNIT 8
Class-Based Exceptions
Lesson 1 Explaining Class-Based Exceptions
326
Lesson 2 Defining and Raising Exceptions Exercise 20: Implement Class-Based Exceptions
332 341
Lesson 3 Implementing Advanced Exception Handling Techniques Exercise 21: Map Exceptions to Each Other
355 363
UNIT OBJECTIVES ●
Explain class-based exceptions
●
Handle class-based exceptions
●
Debug class-based exceptions
●
Define global exception classes
●
Raise class-based exceptions
●
Propagate exceptions
●
Explain the hierarchy of predefined exception classes
●
Explain different ways of handling an exception
●
Retry after exceptions
●
Implement resumable exceptions
●
Map exceptions
© Copyright. All rights reserved.
325
Unit 8 Lesson 1 Explaining Class-Based Exceptions
LESSON OVERVIEW This lesson explains how to handle and debug class-based exceptions. Business Example You must use the new exceptions concept in your ABAP Object programs. For this reason, you require the following knowledge: ●
An understanding of class-based exceptions
●
An understanding of how to handle class-based exceptions
●
An understanding of how to debug class-based exceptions
LESSON OBJECTIVES After completing this lesson, you will be able to: ●
Explain class-based exceptions
●
Handle class-based exceptions
●
Debug class-based exceptions
Class-Based Exceptions An exception is a situation that arises while a program is being executed during which there is no point to continue the normal program flow. SAP Web AS 6.10 introduced a new ABAP Objects exception concept that exists parallel to the existing concept based on sy-subrc. Exceptions and exception handling are now based on classes. This new ABAP Objects exception concept enhanced the classic way of handling exception using sy-subrc.
Hint: Note that the use of class-based exceptions is not limited to object-oriented contexts. Class-based exceptions can be raised and handled in all processing blocks. In particular, all previously catchable runtime errors can be handled as class-based exceptions.
326
© Copyright. All rights reserved.
Lesson: Explaining Class-Based Exceptions
Figure 132: An Overview of the Class-Based Exception Concept
In the new exception concept, an exception is represented by an exception object. An exception object is an instance of an exception class. The attribute values of the exception object contain information about the respective error situation. Raising a class-based exception means instantiating an exception class and setting the attributes. Handling a classbased exception involves evaluating the exception object and its attribute values. Class-based exceptions are raised either by the RAISE EXCEPTION statement or by the runtime environment. You catch and handle class-based exceptions with the TRY...CATCH...ENDTRY structure.
Hierarchy of Exception Classes
Figure 133: Exception Classes – The Inheritance Hierarchy
You can define your own exception classes, but the system already includes a range of predefined exception classes – particularly for exceptions in the runtime environment. You
© Copyright. All rights reserved.
327
Unit 8: Class-Based Exceptions
can create exception classes globally in the Class Builder, but you can also define local exception classes within a program or global class. The names of global exception classes always start with CX_. Those global exception classes that the runtime environment uses start with CX_SY_. We recommend that you start the names of local exception classes with LCX_. All exception classes are derived from one exception class, CX_ROOT. Therefore, you can generically access any exception object through a reference variable, REF TO CX_ROOT. However, a new exception class is not allowed to inherit directly from CX_ROOT, derive any new exception class directly or indirectly from one of the subclasses CX_ROOT CX_NO_CHECK, CX_DYNAMIC_CHECK, or CX_STATIC_CHECK. Through this, all exception classes are subdivided into three groups. Depending on the group to which a given exception belongs, the exception is treated differently by syntax check and runtime environment. The default group is CX_STATIC_CHECK, which ensures maximum syntax check and program stability. Use the other groups only in special cases. The GET_SOURCE_POSITION method returns the name of the main program or include program and also the line number in the source code where the exception occurs. The GET_TEXT method returns an exception text in the form of a string. This method is not defined in CX-ROOT directly but in interface IF_MESSAGE, which is implemented by CXROOT.
Class-Based Exception Handling
Figure 134: Structure of a TRY-ENDTRY Block
You can handle an exception if the statement that raised it is enclosed inside a TRY-ENDTRY control structure. You handle the exception using the CATCH statement in the TRY-ENDTRY structure. The TRY block contains the statements for which the exceptions need to be handled. A CATCH block contains the exception handler which is executed if a specified exception has occurred in the associated TRY block. Like all control structures in ABAP Objects, you can nest TRY-ENDTRY structures to any depth. In particular, the TRY block, the CATCH block, and the CLEANUP block can contain complete TRY-ENDTRY structures themselves.
328
© Copyright. All rights reserved.
Lesson: Explaining Class-Based Exceptions
Specify any number of exception classes in the CATCH statement. In this way, you define an exception handler for all these exception classes and their subclasses. If an exception occurs, the system searches for a matching CATCH statement in the TRYENDTRY structure that immediately surrounds the statement. It searches through the CATCH blocks for the relevant exception class or the superclasses from the inheritance hierarchy. If any of the relevant exception classes is found, the program navigates directly to the hander. If the system does not find a matching CATCH statement, it gradually searches outwards in the surrounding TRY-ENDTRY structures. If no handler can be found within the same procedure, the system tries to propagate the exception to the calling program. This process will be discussed in more detail later. If a TRY-ENDTRY structure contains a CLEANUP block, this block is executed when the TRYENDTRY structure is exited because the system cannot find a handler within the TRYENDTRY structure itself but instead in a surrounding TRY-ENDTRY structure or in a calling program. Example Syntax for Handling Predefined Exceptions
Figure 135: Example Syntax for Handling Predefined Exceptions
The figure Example Syntax for Handling Predefined Exceptions, shows an example of syntax for handling predefined exceptions. To analyze the exception object in an exception handler, use the CATCH statement in the form CATCH ... INTO ... You have to specify a suitably typed object reference after the optional addition INTO. The reference can be a reference either to the exception class itself or to any of its superclasses. Just before the system executes CATCH block, the system fills the reference variable so that it points to the exception object describing the present error situation. If the value range for data type I is exceeded in the calculation, the runtime system raises exception CX_SY_ARITHMETIC_OVERFLOW. This exception is handled in the implemented CATCH block. The reference to the appropriate instance is stored in data object GO_EXC in the example. The handler can access the instance’s exception text using the functional
© Copyright. All rights reserved.
329
Unit 8: Class-Based Exceptions
method GET_TEXT. The exception text is stored in the data object GV_TEXT with the type STRING and then displayed as an information message. You can access any other public component of the exception object during exception handling depending on the static type of the reference variable. In the example above, the reference variable is typed as REF TO CX_ROOT, which restricts access to those components defined in CX_ROOT. To access the more-specific components of the exception object, you need a more-specific type reference variable type. You can also use the superclass CX_SY_ARITHMETIC_ERROR and the super-superclass CX_DYNAMIC_CHECK to access the specific components of the exception object. The ABAP keyword documentation for each statement lists the classes whose exceptions may occur when that statement is executed.
Class-Based Exceptions in the Debugger
Figure 136: Class-Based Exceptions in Debugging Mode
If an exception is raised, the system displays name of the exception class in the Exception Raised field in debugging mode. If a CATCH block catches the exception a success message displays. The pointer for the current statement then moves to this CATCH block. Two buttons appear if an exception occurs. Use the buttons to analyze the exception object and to navigate to the point in the source code where the exception occurred respectively.
Hint: For performance reasons, the system does not actually create exception objects if the INTO addition is missing from the respective CATCH statement. In such cases, the Last Exception Object button normally does not appear. To set the ABAP Debugger to always create the exception object, choose the respective option in the debugger settings.
330
© Copyright. All rights reserved.
Lesson: Explaining Class-Based Exceptions
LESSON SUMMARY You should now be able to: ●
Explain class-based exceptions
●
Handle class-based exceptions
●
Debug class-based exceptions
© Copyright. All rights reserved.
331
Unit 8 Lesson 2 Defining and Raising Exceptions
LESSON OVERVIEW This lesson explains how to define and raise global exception classes. Business Example You need to define global exception classes for your ABAP Objects programs. For this reason, you require the following knowledge: ●
An understanding of the definition of global exception classes
●
An understanding of how to raise class-based exceptions
●
An understanding of how to implement exception propagation
LESSON OBJECTIVES After completing this lesson, you will be able to:
332
●
Define global exception classes
●
Raise class-based exceptions
●
Propagate exceptions
© Copyright. All rights reserved.
Lesson: Defining and Raising Exceptions
Definition of Global Exception Classes
Figure 137: Creating Global Exception Classes
You use Class Builder to create a global class as described in SAP Library. When you enter the name of global class, use the prefix CX_. Choose the Exception Class option as the class type.
Note: As of SAP NetWeaver Application Server 6.40 (SAP NW AS 6.40), there is a message class checkbox that you may select when you create the class. This option allows the text from the exception classes to be reused from any message class, the text of which is stored in table T100. You can not mix text from message classes and the OTR in one exception class. In releases before SAP NW AS 6.40, exception texts were stored solely in the Online Text Repository (OTR). When you create an exception class, do not change the default entry for Inherits from unless you are fully aware of the consequences of making the change. Define additional attributes in your exception class as necessary (for example, for generic extensions to exception texts).
© Copyright. All rights reserved.
333
Unit 8: Class-Based Exceptions
Hint: If such an attribute is public, the Class Builder automatically adjusts the instance constructor of the exception class. A new input parameter is generated and a value can be set for this attribute when raising the exception. The import parameter is generated with the same name as the attribute. By default, the parameter is optional. You may declare it mandatory by editing the constructor’s signature. Define Variable Exception Texts
Figure 138: Define Variable Exception Texts
Save as many exception texts as you need. When you save exception texts, you can insert attributes as parameters in the static text using the form &&.
Note: For the first text you create, always use the predefined static constant as an ID. The constant always has the same name as the exception class itself. If the raiser of the exception does not specify a text when the exception is raised, the system uses the text with this ID. You define other IDs for all other texts. Class Builder then generates identically named static constants automatically. When the exception is raised, pass one of these constants to import parameter TEXTID to specify the appropriate text for the exception instance.
334
© Copyright. All rights reserved.
Lesson: Defining and Raising Exceptions
Note: In releases before SAP NW AS 6.40, exception texts for global exception classes and their translations were stored in OTR. You can assign several texts to a single class. You assign a text to an exception using the TEXTID attribute, which contains the globally unique ID of the text object in OTR in an instance at runtime. The GET_TEXT method then exports this text, replaces any text parameters with the contents of the relevant attributes as required, and returns the text as a character string. Activate the exception class after filling in the exception texts. To Define Global Exception Classes 1. In the Class Builder, in the unnamed dropdown list on the left of the screen, choose Class/ Interface. 2. In the unnamed field, enter the new exception class name, use the prefix ZCX_. Press ENTER. 3. To create the class, choose Yes. A Create Class dialog box displays. 4. Select the Exception Class radio button, and choose the With Message Class checkbox if you want the exception texts to come from an existing message class. Enter a short description. 5. Do not change the default Superclass CX_STATIC_CHECK. Choose Save. The Create Object Directory Entry dialog box displays. 6. In the Create Object Directory Entry dialog box, enter your package name and choose Save. A Prompt for transportable Workbench request dialog box displays. 7. In the Prompt for transportable Workbench dialog box, accept the defaults and choose Continue. 8. Define additional attributes in your exception class if necessary (for example, to use in the exception texts). Note: If these attributes are public, the Class Builder automatically adjusts the instance constructor of the exception class: A new input parameter is generated so that a value can be provided for this attribute when raising the exception. The import parameter is generated with the same name as the attribute. By default the parameter is optional. You may declare it as mandatory by editing the constructor’s signature. 9. Choose the Texts tab in the Class Builder, and create as many exception texts as you need. When you do so, you can insert your attributes as parameters in the static text in the form &&.
© Copyright. All rights reserved.
335
Unit 8: Class-Based Exceptions
Note: For the first text you create, always use the predefined static constant as an ID. It always has the same name as the exception class itself. If no text is specified explicitly when the exception is raised, the text with this ID is used. For all other texts, you define other IDs. The Class Builder then generates identically named static constants automatically. When the exception is raised, you pass one of these constants to the import parameter TEXTID, to specify the appropriate text for the exception instance.
Use of the RAISE EXCEPTION Statement
Figure 139: Variants of Statement RAISE EXCEPTION
The figure Variants of Statement RAISE EXCEPTION, shows examples for statement RAISE EXCEPTION. Raising class-based exceptions is done using the RAISE EXCEPTION statement. There are two variants of the statement. Variants of Statement RAISE EXCEPTION ... RAISE EXCEPTION TYPE [EXPORTING ...]. This statement creates a new exception object that is an instance of the class. RAISE EXCEPTION . This statement uses an existing exception object that the one points to. The exception object was either created directly using a CREATE OBJECT statement or caught in a previous CATCH ... INTO ...statement. When using the first variant, it is possible to provide values for the constructor parameters using the EXPORTING addition. One of these parameters is used to set the exception text in the new exception object.
336
© Copyright. All rights reserved.
Lesson: Defining and Raising Exceptions
Exception Texts
Figure 140: Setting the Exception Text
All exception classes offer an optional parameter TEXTID in their constructors. Use this parameter if more than one message text is available in the exception class and you do not want to raise the exception with the default text. For each text defined on the Texts tab page, the Class Builder generates a public constant of the same name. Constants may also be inherited from the superclasses of the exception class. By default, the system raises an exception with the text that has the same name as the exception class. To raise the exception with another text, use the corresponding constant as the actual parameter for constructor parameter TEXTID.
Note: The type of the constants and parameter TEXTID in the constructor is determined by whether or not the exception class was created with the With message class flag. If the exception class still uses OTR texts, the constants are of type CHAR and contain a technical ID of the OTR text. If the exception class uses a message class, the constants are structures containing the name of the message class, the message number.
© Copyright. All rights reserved.
337
Unit 8: Class-Based Exceptions
Exception Propagation
Figure 141: Propagating Class-Based Exceptions
The handling of exceptions that occur within procedures does not have to lie within the same procedure. Instead, the procedure can propagate the exception to its caller. The caller can then handle the exception or propagate it to its own caller. The highest levels to which an exception can be propagated are processing blocks without local data areas, that is, event blocks or dialog modules. These processing blocks have to handle the propagated exceptions. Otherwise, a runtime error occurs. The same is true for exceptions raised within such processing blocks. To propagate an exception from a procedure, you generally use the RAISING addition when you define the procedure interface. In methods of local classes and subroutines, specify the RAISING addition directly when you are defining the procedure. For example: METHODS meth_name ... RAISING cx_... cx_... or FORM subr_name ... RAISING cx_... cx_.... The RAISING addition is followed by a list of the exception classes whose instances are to be propagated. In methods of global classes, enter exception classes whose instances are to be propagated into the exception table of the method in the Class Builder. You also need to set the Exception Class flag for each exception table. The process is similar for function modules. To set the indicator in Function Builder, choose the Exceptions tab.
Hint: A single method, subroutine, or function module can raise only one type of exception, that is, either class-based or conventional.
338
© Copyright. All rights reserved.
Lesson: Defining and Raising Exceptions
Propagating Exceptions Over Several Hierarchy – Levels
Figure 142: Propagating Exceptions Over Several Hierarchy – Levels
Propagation of class-based exception does not require that the calling method actually handles the exception. The caller may pass the exception to its own caller even without handling it. In the example, the constructor propagates the CX_EXC exception raised by the GET_TECH_ATTR method. When the error occurs and the program raises the exception, the program flow jumps directly to the CATCH block in the main program.
Note: If the constructor implements the optional CLEANUP block, the system executes this block before the CATCH block of the main program.
© Copyright. All rights reserved.
339
Unit 8: Class-Based Exceptions
340
© Copyright. All rights reserved.
Unit 8 Exercise 20 Implement Class-Based Exceptions
Business Example Your program uses the class-based exception concept if an invalid plane type is provided when creating an airplane instance.
Note: This exercise uses the main program file ZBC401_##_MAIN completed in the previous exercise. If not complete, copy the model solution from the previous exercise. In the exercises for this course, when the input values include ##, replace ## with your group number. Template SAPBC401_GCL_S2 Solution SAPBC401_EXC_S1 (Main program) CX_INVALID_PLANETYPE (exception class) Create a Global Exception Class Create a global exception class for an invalid airplane type. 1. Create a global exception class called ZCX_##_INVALID_PLANETYPE (where ## is your two-digit group number). Hint: You want the syntax check to ensure that exceptions based on this class are either handled directly or propagated. Choose the superclass accordingly. In the exception class, use texts from a message class instead of freely defined texts. 2. Add an attribute for the airplane type and assign the type S_PLANETYE to it. Make sure a corresponding parameter is defined in the signature of the constructor. Hint: You cannot define the constructor of an exception class directly. If you define the attribute as public, a corresponding import parameter is added to the constructor by the framework. 3. Create a default error message. Include a placeholder in the message text so that it can be enhanced dynamically to include the airplane type.
© Copyright. All rights reserved.
341
Unit 8: Class-Based Exceptions
Hint: You can define your own message class and message or use message 020 from message class BC401. Raise an Exception With Your Own Exception Type Raise the new exception in method GET_TECHNICAL_ATTRIBUTES of your local class LCL_AIRPLANE. 1. In the main program, edit the definition of local class LCL_AIRPLANE. Remove the classical, non class-based exception WRONG_PLANETYPE from the signature of method GET_TECHNICAL_ATTRIBUTES and replace it with your new class-based exception ZCX_##_INVALID_PLANETYPE. 2. Edit the implementation of method GET_TECHNICAL_ATTRIBUTES and raise the classbased exception instead of the classical exception. Ensure that the wrong plane type value is handed over to the constructor and stored in the exception object. Propagate the Raised Exception Propagate the class-based exception explicitly through the entire call hierarchy so that you must handle it only once in the main program. 1. Edit the definition of local class LCL_AIRPLANE. Remove the classical, non class-based exception WRONG_PLANETYPE from the signature of method CONSTRUCTOR and replace it with your new class-based exception, ZCX_##_INVALID_PLANETYPE. 2. Edit the implementation of the constructor of local class LCL_AIRPLANE. While calling method GET_TECHNICAL_ATTRIBUTES, remove the handling of classical exception WRONG_PLANETYPE. 3. Why is it not necessary to handle the class-based exception ZCX_##_INVALID_PLANETYPE here?
4. Edit the definition of local class LCL_PASSENGER_PLANE. Remove the classical, non class-based exception WRONG_PLANETYPE from the signature of the CONSTRUCTOR method and replace it with your new class-based exception ZCX_##_INVALID_PLANETYPE. 5. Edit the implementation of the constructor of local class LCL_PASSENGER_PLANE. In the call of SUPER->CONSTRUCTOR, remove the handling of classical exception WRONG_PLANETYPE. 6. Repeat the previous steps with local class LCL_CARGO_PLANE. Handle the Class-Based Exception Handle the raised exception in the main program whenever an airplane object is created. 1. Define a global reference variable for this purpose (suggested name: GO_INV_PLANETYPE) and type it with your exception class ZCX_##_INVALID_PLANETYPE.
342
© Copyright. All rights reserved.
Lesson: Defining and Raising Exceptions
2. In the CREATE OBJECT statement for airplanes (instances of LCL_AIRPLANE, LCL_PASSENGER_PLANE, and LCL_CARGO_PLANE), remove the handling of the classical, non class-based exception WRONG_PLANETYPE. 3. Surround each CREATE OBJECT statement for airplanes with a TRY-ENDTRY structure. Add a CATCH block for your exception ZCX_##_INVALID_PLANETYPE. In the case of an exception, let reference variable GO_INV_PLANETYPE point to the exception object. 4. Read the error text from the exception object and output it to the ABAP list. Hint: It is not possible to use the result of functional methods directly in the WRITE statement. You need to define a variable to store the text (suggested name: GV_TEXT with data type STRING). 5. Save, check, and activate the program. 6. Run your program. For test purposes, create an airplane with a wrong plane type and debug the propagation of the exception.
© Copyright. All rights reserved.
343
Unit 8 Solution 20 Implement Class-Based Exceptions
Business Example Your program uses the class-based exception concept if an invalid plane type is provided when creating an airplane instance.
Note: This exercise uses the main program file ZBC401_##_MAIN completed in the previous exercise. If not complete, copy the model solution from the previous exercise. In the exercises for this course, when the input values include ##, replace ## with your group number. Template SAPBC401_GCL_S2 Solution SAPBC401_EXC_S1 (Main program) CX_INVALID_PLANETYPE (exception class) Create a Global Exception Class Create a global exception class for an invalid airplane type. 1. Create a global exception class called ZCX_##_INVALID_PLANETYPE (where ## is your two-digit group number). Hint: You want the syntax check to ensure that exceptions based on this class are either handled directly or propagated. Choose the superclass accordingly. In the exception class, use texts from a message class instead of freely defined texts. a) In the unnamed dropdown list on the left of the screen, choose Class /Interface, specify the name of the package ZCX_##_INVALID_PARTNER and press ENTER. A Create Class/Interface dialog box displays. b) To create the Exception Class, choose Yes. A Create Class dialog box displays. c) In the Create Class dialog box, select Exception Class radio button and select the With Message Class checkbox. Enter a short description and choose Save. A Create Object Directory Entry dialog box displays.
344
© Copyright. All rights reserved.
Lesson: Defining and Raising Exceptions
d) In the Create Object Directory Entry dialog box, enter your package name and choose Save. A Prompt for transportable Workbench request dialog box displays. e) In the Prompt for transportable Workbench request dialog box, accept the defaults and choose Continue. 2. Add an attribute for the airplane type and assign the type S_PLANETYE to it. Make sure a corresponding parameter is defined in the signature of the constructor. Hint: You cannot define the constructor of an exception class directly. If you define the attribute as public, a corresponding import parameter is added to the constructor by the framework. a) On the Attributes tab page, enter the attribute name and type and choose the visibility. 3. Create a default error message. Include a placeholder in the message text so that it can be enhanced dynamically to include the airplane type. Hint: You can define your own message class and message or use message 020 from message class BC401. a) On the Texts tab page, select the default text and choose Message Text. b) Enter the message class and message number in the relevant fields. In the Attr. 1 field, use the value that helps to choose attribute PLANETYPE. Raise an Exception With Your Own Exception Type Raise the new exception in method GET_TECHNICAL_ATTRIBUTES of your local class LCL_AIRPLANE. 1. In the main program, edit the definition of local class LCL_AIRPLANE. Remove the classical, non class-based exception WRONG_PLANETYPE from the signature of method GET_TECHNICAL_ATTRIBUTES and replace it with your new class-based exception ZCX_##_INVALID_PLANETYPE. a) See the source code extract from the model solution. 2. Edit the implementation of method GET_TECHNICAL_ATTRIBUTES and raise the classbased exception instead of the classical exception. Ensure that the wrong plane type value is handed over to the constructor and stored in the exception object. a) See the source code extract from the model solution. Propagate the Raised Exception Propagate the class-based exception explicitly through the entire call hierarchy so that you must handle it only once in the main program. 1. Edit the definition of local class LCL_AIRPLANE. Remove the classical, non class-based exception WRONG_PLANETYPE from the signature of method CONSTRUCTOR and replace it with your new class-based exception, ZCX_##_INVALID_PLANETYPE. a) See the source code extract from the model solution.
© Copyright. All rights reserved.
345
Unit 8: Class-Based Exceptions
2. Edit the implementation of the constructor of local class LCL_AIRPLANE. While calling method GET_TECHNICAL_ATTRIBUTES, remove the handling of classical exception WRONG_PLANETYPE. a) See the source code extract from the model solution. 3. Why is it not necessary to handle the class-based exception ZCX_##_INVALID_PLANETYPE here? It is because this exception is propagated in the signature of the constructor of LCL_AIRPLANE. 4. Edit the definition of local class LCL_PASSENGER_PLANE. Remove the classical, non class-based exception WRONG_PLANETYPE from the signature of the CONSTRUCTOR method and replace it with your new class-based exception ZCX_##_INVALID_PLANETYPE. a) See the source code extract from the model solution. 5. Edit the implementation of the constructor of local class LCL_PASSENGER_PLANE. In the call of SUPER->CONSTRUCTOR, remove the handling of classical exception WRONG_PLANETYPE. a) See the source code extract from the model solution. 6. Repeat the previous steps with local class LCL_CARGO_PLANE. a) See the source code extract from the model solution. Handle the Class-Based Exception Handle the raised exception in the main program whenever an airplane object is created. 1. Define a global reference variable for this purpose (suggested name: GO_INV_PLANETYPE) and type it with your exception class ZCX_##_INVALID_PLANETYPE. a) See the source code extract from the model solution. 2. In the CREATE OBJECT statement for airplanes (instances of LCL_AIRPLANE, LCL_PASSENGER_PLANE, and LCL_CARGO_PLANE), remove the handling of the classical, non class-based exception WRONG_PLANETYPE. a) See the source code extract from the model solution. 3. Surround each CREATE OBJECT statement for airplanes with a TRY-ENDTRY structure. Add a CATCH block for your exception ZCX_##_INVALID_PLANETYPE. In the case of an exception, let reference variable GO_INV_PLANETYPE point to the exception object. a) See the source code extract from the model solution. 4. Read the error text from the exception object and output it to the ABAP list. Hint: It is not possible to use the result of functional methods directly in the WRITE statement. You need to define a variable to store the text (suggested name: GV_TEXT with data type STRING). a) See the source code extract from the model solution. 5. Save, check, and activate the program.
346
© Copyright. All rights reserved.
Lesson: Defining and Raising Exceptions
a) Save your program. b) To check your program, on the application toolbar choose the Check button. c) To activate your program, on the application toolbar choose the Activate button. 6. Run your program. For test purposes, create an airplane with a wrong plane type and debug the propagation of the exception. a) To run your program, on the application toolbar choose the Direct Processing button. Include: BC401_EXC_S1_CARRIER *------------------------------------------------* * CLASS lcl_airplane DEFINITION *------------------------------------------------* CLASS lcl_airplane DEFINITION. PUBLIC SECTION.
* *
METHODS: constructor IMPORTING iv_name TYPE string iv_planetype TYPE saplane-planetype EXCEPTIONS wrong_planetype, RAISING cx_invalid_planetype, display_attributes. CLASS-METHODS: display_n_o_airplanes, class_constructor. EVENTS: airplane_created. PROTECTED SECTION. CONSTANTS: c_pos_1 TYPE i VALUE 30. PRIVATE SECTION. TYPES: ty_planetypes TYPE STANDARD TABLE OF saplane WITH NON-UNIQUE KEY planetype. DATA: mv_name mv_planetype mv_weight mv_tankcap
TYPE TYPE TYPE TYPE
string, saplane-planetype, saplane-weight, saplane-tankcap.
CLASS-DATA: gv_n_o_airplanes TYPE i, gt_planetypes TYPE ty_planetypes. CLASS-METHODS: get_technical_attributes IMPORTING
© Copyright. All rights reserved.
347
Unit 8: Class-Based Exceptions
* *
iv_type TYPE saplane-planetype EXPORTING ev_weight TYPE saplane-weight ev_tankcap TYPE saplane-tankcap EXCEPTIONS wrong_planetype. RAISING cx_invalid_planetype.
ENDCLASS.
"lcl_airplane DEFINITION
*-------------------------------------------------* * CLASS lcl_airplane IMPLEMENTATION *-------------------------------------------------* CLASS lcl_airplane IMPLEMENTATION. METHOD class_constructor. SELECT * FROM saplane INTO TABLE gt_planetypes. ENDMETHOD. "class_constructor METHOD constructor. mv_name = iv_name. mv_planetype = iv_planetype. get_technical_attributes( EXPORTING iv_type = iv_planetype IMPORTING ev_weight = mv_weight ev_tankcap = mv_tankcap ). gv_n_o_airplanes = gv_n_o_airplanes + 1. RAISE EVENT airplane_created. * * * * * * * * * * * * * * *
get_technical_attributes( EXPORTING iv_type = iv_planetype IMPORTING ev_weight = mv_weight ev_tankcap = mv_tankcap EXCEPTIONS wrong_planetype = 1 ). IF sy-subrc <> 0. RAISE wrong_planetype. ELSE. gv_n_o_airplanes = gv_n_o_airplanes + 1. RAISE EVENT airplane_created. ENDIF. ENDMETHOD. "constructor METHOD display_attributes. WRITE: / icon_ws_plane AS ICON, / 'Name of Airplane'(001) , / 'Type of Airplane:'(002), / 'Weight:'(003), LEFT-JUSTIFIED, / 'Tank capacity:'(004), LEFT-JUSTIFIED. ENDMETHOD.
348
AT c_pos_1 mv_name, AT c_pos_1 mv_planetype, AT c_pos_1 mv_weight AT c_pos_1 mv_tankcap
"display_attributes
© Copyright. All rights reserved.
Lesson: Defining and Raising Exceptions
METHOD display_n_o_airplanes. SKIP. WRITE: / 'Number of airplanes:'(ca1), AT c_pos_1 gv_n_o_airplanes LEFT-JUSTIFIED. ENDMETHOD. "display_n_o_airplanes METHOD get_technical_attributes. DATA: ls_planetype TYPE saplane. READ TABLE gt_planetypes INTO ls_planetype WITH TABLE KEY planetype = iv_type TRANSPORTING weight tankcap. IF sy-subrc = 0. ev_weight = ls_planetype-weight. ev_tankcap = ls_planetype-tankcap. ELSE. * RAISE wrong_planetype. RAISE EXCEPTION TYPE cx_invalid_planetype EXPORTING planetype = iv_type. ENDIF. ENDMETHOD. "get_technical_attributes ENDCLASS.
"lcl_airplane IMPLEMENTATION
*-------------------------------------------------* * CLASS lcl_cargo_plane DEFINITION *---------------------------------------------------* CLASS lcl_cargo_plane DEFINITION INHERITING FROM lcl_airplane. PUBLIC SECTION.
* *
METHODS: constructor IMPORTING iv_name TYPE string iv_planetype TYPE saplane-planetype iv_cargo TYPE s_plan_car RAISING cx_invalid_planetype, EXCEPTIONS wrong_planetype, display_attributes REDEFINITION. PRIVATE SECTION. DATA: mv_cargo TYPE s_plan_car.
ENDCLASS.
"lcl_cargo_plane DEFINITION
*-----------------------------------------------* * CLASS lcl_cargo_plane IMPLEMENTATION *-----------------------------------------------* CLASS lcl_cargo_plane IMPLEMENTATION. METHOD constructor. super->constructor(
© Copyright. All rights reserved.
349
Unit 8: Class-Based Exceptions
* * * * *
EXPORTING iv_name = iv_name iv_planetype = iv_planetype ). EXCEPTIONS wrong_planetype = 1 ). IF sy-subrc <> 0. RAISE wrong_planetype. ENDIF. mv_cargo = iv_cargo. ENDMETHOD. "constructor METHOD display_attributes. super->display_attributes( ). WRITE: / 'Max Cargo:'(005), AT c_pos_1 mv_cargo LEFT-JUSTIFIED. ULINE. ENDMETHOD. "display_attributes
ENDCLASS.
"lcl_cargo_plane IMPLEMENTATION
*------------------------------------------------* * CLASS lcl_passenger_plane DEFINITION *------------------------------------------------* CLASS lcl_passenger_plane DEFINITION INHERITING FROM lcl_airplane. PUBLIC SECTION.
* *
METHODS: constructor IMPORTING iv_name TYPE string iv_planetype TYPE saplane-planetype iv_seats TYPE s_seatsmax EXCEPTIONS wrong_planetype RAISING cx_invalid_planetype, display_attributes REDEFINITION. PRIVATE SECTION. DATA: mv_seats TYPE s_seatsmax.
ENDCLASS.
"lcl_passenger_plane DEFINITION
*-----------------------------------------------* * CLASS lcl_passenger_plane IMPLEMENTATION *-----------------------------------------------* CLASS lcl_passenger_plane IMPLEMENTATION. METHOD constructor. super->constructor( EXPORTING iv_name = iv_name iv_planetype = iv_planetype ). * *
350
EXCEPTIONS wrong_planetype = 1 ).
© Copyright. All rights reserved.
Lesson: Defining and Raising Exceptions
* * *
IF sy-subrc <> 0. RAISE wrong_planetype. ENDIF. mv_seats = iv_seats. ENDMETHOD. "constructor
METHOD display_attributes. super->display_attributes( ). WRITE: / 'Max Seats:'(006), AT c_pos_1 mv_seats LEFT-JUSTIFIED. ULINE. ENDMETHOD. "display_attributes ENDCLASS. "lcl_passenger_plane IMPLEMENTATION *---------------------------------------------------* * CLASS lcl_carrier DEFINITION *---------------------------------------------------* CLASS lcl_carrier DEFINITION. ... ENDCLASS.
"lcl_carrier DEFINITION
*---------------------------------------------------* * CLASS lcl_carrier IMPLEMENTATION *---------------------------------------------------* CLASS lcl_carrier IMPLEMENTATION. ... ENDCLASS.
"lcl_carrier IMPLEMENTATION
Main program: SAPBC401_EXC_S1 REPORT
sapbc401_exc_s1.
TYPE-POOLS icon. INCLUDE bc401_exc_s1_agency. INCLUDE bc401_exc_s1_carrier. INCLUDE bc401_exc_s1_rental. DATA: go_hotel go_vehicle go_truck go_bus go_rental go_passenger go_cargo go_carrier go_agency
TYPE TYPE TYPE TYPE TYPE TYPE TYPE TYPE TYPE
REF REF REF REF REF REF REF REF REF
TO TO TO TO TO TO TO TO TO
cl_hotel2, lcl_vehicle, lcl_truck, lcl_bus, lcl_rental, lcl_passenger_plane, lcl_cargo_plane, lcl_carrier, lcl_travel_agency.
DATA: gv_text TYPE string, gx_inv_planetype TYPE REF TO cx_invalid_planetype. START-OF-SELECTION.
© Copyright. All rights reserved.
351
Unit 8: Class-Based Exceptions
******************* ******* create travel_agency CREATE OBJECT go_agency EXPORTING iv_name = 'Travel&Smile Travel'. ******* create hotel CREATE OBJECT go_hotel EXPORTING iv_name = 'Sleep Well Hotel' iv_beds = 345. ******* create rental CREATE OBJECT go_rental EXPORTING iv_name = 'Happy Car Rental'. ******* create truck CREATE OBJECT go_truck EXPORTING iv_make = 'MAN' iv_cargo = 45. ******* create truck CREATE OBJECT go_bus EXPORTING iv_make = 'Mercedes' iv_passengers = 80. ******* create truck CREATE OBJECT go_truck EXPORTING iv_make = 'VOLVO' iv_cargo = 48. ***** Create Carrier CREATE OBJECT go_carrier EXPORTING iv_name = 'Smile&Fly'. ***** Passenger Plane TRY. CREATE OBJECT go_passenger EXPORTING iv_name = 'LH BERLIN' iv_planetype = '747-500' iv_seats = 345. CATCH cx_invalid_planetype INTO gx_inv_planetype. gv_text = gx_inv_planetype->get_text( ). WRITE: / icon_failure AS ICON, gv_text. ENDTRY. * * * *
352
CREATE OBJECT go_passenger EXPORTING iv_name = 'LH BERLIN' iv_planetype = '747-400'
© Copyright. All rights reserved.
Lesson: Defining and Raising Exceptions
* * * * * * * *
iv_seats = 345 EXCEPTIONS wrong_planetype = 1. IF sy-subrc <> 0. WRITE: / icon_failure AS ICON, 'Wrong plane type'. ENDIF.
***** cargo Plane TRY. CREATE OBJECT go_cargo EXPORTING iv_name = 'US Hercules' iv_planetype = '747-200F' iv_cargo = 533. CATCH cx_invalid_planetype INTO gx_inv_planetype. gv_text = gx_inv_planetype->get_text( ). WRITE: / icon_failure AS ICON, gv_text. ENDTRY. * * * * * * * * * * * * *
CREATE OBJECT go_cargo EXPORTING iv_name = 'US Hercules' iv_planetype = '747-200F' iv_cargo = 533 EXCEPTIONS wrong_planetype = 1. IF sy-subrc <> 0. WRITE: / icon_failure AS ICON, 'Wrong plane type'. ENDIF.
******* show attributes of all partners of travel_agency go_agency->display_attributes( ).
© Copyright. All rights reserved.
353
Unit 8: Class-Based Exceptions
LESSON SUMMARY You should now be able to:
354
●
Define global exception classes
●
Raise class-based exceptions
●
Propagate exceptions
© Copyright. All rights reserved.
Unit 8 Lesson 3 Implementing Advanced Exception Handling Techniques
LESSON OVERVIEW This lesson explains the implementation of advanced exception handling techniques. Business Example You need to use advanced exception handling techniques to catch exceptions and to retry after exception handling in your ABAP Objects programs. For this reason, you require the following knowledge: ●
An understanding of predefined exception classes
●
An understanding of how to handle an exception class
●
An understanding of how to retry after an exception
LESSON OBJECTIVES After completing this lesson, you will be able to: ●
Explain the hierarchy of predefined exception classes
●
Explain different ways of handling an exception
●
Retry after exceptions
●
Implement resumable exceptions
●
Map exceptions
© Copyright. All rights reserved.
355
Unit 8: Class-Based Exceptions
The Hierarchy of Predefined Exception Classes
Figure 143: Integration of Standard Exceptions in the Runtime System
The figure shows how the standard exceptions in the runtime system are integrated into the inheritance hierarchy of the exception classes. The choice of the superclass influences the way that the syntax check and the runtime environment handle a given exception. Some of the standard exception classes are as follows: ●
CX_STATIC_CHECK If an exception class inherits from CX_STATIC_CHECK, you must either handle the relevant exception or propagate it using the RAISING addition. If the exception is neither handled nor propagated using the RAISING addition, the syntax check displays a warning. When you define a new global exception class, CX_STATIC_CHECK is defined as the superclass by default.
●
CX_DYNAMIC_CHECK For subclasses of CX_DYNAMIC_CHECK, the syntax check displays no warning if exceptions are neither handled nor propagated with the RAISING addition.If an exception is raised at runtime and you neither handle nor propagate it, the system ends the program with a runtime error. Note: Typical examples of this situation are the predefined exceptions CX_SY_... for errors that occur in the runtime environment. These are usually subclasses of CX_DYNAMIC_CHECK.
●
356
CX_NO_CHECK
© Copyright. All rights reserved.
Lesson: Implementing Advanced Exception Handling Techniques
For subclasses of CX_NO_CHECK, you cannot propagate the corresponding exceptions explicitly using the RAISING addition. If you do not handle these exceptions in the processing block where they occur, they are automatically propagated. If the calling block does not handle the exceptions, they are automatically propagated further on to the highest call hierarchy level. If the exceptions are not handled on the top level, a runtime error occurs at the point where they were raised. Some predefined exceptions with the prefix CX_SY_... for error situations in the runtime environment are subclasses of CX_NO_CHECK.
Exception Handling After an exception was caught in a CATCH statement, you can handle it in many different ways. Techniques to Handle an Exception Caught in a CATCH Statement 1. Continue the program behind an ENDTRY statement after taking one of the following actions: ●
Ignoring the exception (do nothing)
●
Issuing a warning
●
Writing to a protocol
●
Correcting the situation
2. Remove the cause of the error and start again from one of the following points: ●
●
From the beginning of the corresponding TRY block using statement RETRY that is new as of SAP NW 7.0 EhP 2. From where the exception occurred (using statement RESUME that is new as of SAP NW 7.0 EhP 2).
3. Raise and propagate one of the following exceptions: ●
The same exception object again using RAISE EXCEPTION .
●
A new exception using RAISE EXCEPTION TYPE .
© Copyright. All rights reserved.
357
Unit 8: Class-Based Exceptions
The RETRY Statement
Figure 144: RETRY statement
When you handle an exception in a CATCH block, use the RETRY statement to go back to the TRY statement of the respective TRY-ENDTRY structure, for example, if the cause for the exception was removed during the handling. Hint: This technique is new with Release SAP NetWeaver 7.0 EhP 2.
In the example, the main program catches the exception that the constructor raised and propagated. After analyzing the exception object and correcting the error situation, the main program repeats the whole TRY block using the RETRY statement.
Caution: You must use RETRY with some caution. If you do not remove the cause of the exception properly, your program will go into an infinite loop.
358
© Copyright. All rights reserved.
Lesson: Implementing Advanced Exception Handling Techniques
Implementation of Resumable Exceptions
Figure 145: Resume Execution After a Resumable Exception
Use the RESUME statement to resume a program immediately after the statement that raised the exception in the source code. You must satisfy the following prerequisites to use the RESUME statement: 1. The exception must be caught with CATCH statement using the addition BEFORE UNWIND. This ensures that the context of the exception is kept alive for a possible RESUME. If the CATCH block exited without the RESUME statement, the system deletes the context of the exception after the CATCH block is exited. 2. The exception must be raised with the RAISE RESUMABLE ... variant of the RAISE EXCEPTION statement. This prepares the raising processing lock for the RESUME. 3. If the exception is propagated, you must mark it as resumable on all hierarchy levels by using the RAISING RESUMABLE ( ... ) addition with the name of the exception class inside the brackets. This prepares all methods that propagate the exception for a possible RESUME. Hint: There is a checkbox for indicating the use of class base exceptions in the interface of a function module and the signature of a method. When checked, the function module or method must use all class-based exceptions. When left unchecked. all classic exceptions must be used. The handler of a given exception checks whether, at runtime a given exception was raised and propagated resumable or not. All exception objects provide public instance attribute IS_RESUMABLE, which is set to ’X’ or ’ ’ by the framework, depending on how the exception
© Copyright. All rights reserved.
359
Unit 8: Class-Based Exceptions
was raised and propagated. If you resume a non-resumable exception, you cause a runtime error (exception class CX_SY_ILLEGAL_HANDLER). Resume Execution After a Resumable Exception In the example, shown in the figure, method GET_TECH_ATTR raises and propagates the exception; the constructor propagates the exception further. All raising and propagating is setup to be resumable. The main program handles the exception with CATCH BEFORE UNWIND ..., checks that the exception indeed is resumable, and issues the RESUME statement. The system resumes the execution of GET_TECH_ATTR immediately after the RAISE RESUMABLE EXCEPTION statement is executed.
Hint: In this example, you keep the context of the exception. Without the BEFORE UNWIND addition, the system deletes the newly created instance before executing the CATCH block. Resuming the GET_GET_TECH_ATTR method and the constructor would not be possible.
Exception Mapping
Figure 146: Mapping Exceptions to Each Other
After catching an exception, the program can raise a second exception, and so on. An exception object becomes invalid once the program leaves the CATCH block. Therefore, the handler on the top level can only access the last exception object. However, you can chain exception objects, that is, you can let one exception object point to the one before, which points to the one before it, and so on. The handler of an exception may follow the chain and evaluates each exception object in the sequence. All exception classes provide a public instance attribute PREVIOUS. You type the attribute with REF TO CX_ROOT to point to arbitrary exception objects. The constructors of all
360
© Copyright. All rights reserved.
Lesson: Implementing Advanced Exception Handling Techniques
exception classes have an import parameter, PREVIOUS, of the same type, which can be used to link an existing exception object to a new one. In the example in the figure, the constructor catches the exception that has been raised by the GET_TECH_ATTR method. After analyzing the exception, the constructor raises a new exception of a different exception class. It chains the existing exception object to the new one by passing a reference to the existing object to the constructor of the new object. As a result, attribute PREVIOUS of the new exception object points to the exception object that preceded it. The main program catches the second exception and accesses to the second exception object. However, by using public attribute PREVIOUS, the main program can navigate to the other exception object and analyze it. The main program can access each instance in a chain of exceptions and follow the history of the raised exceptions in the call hierarchy. Implementation of Re-Raise Exceptions
Figure 147: Re-raising an Existing Exception Object
You raise class-based exceptions with one of the following variants of statement RAISE EXCEPTION: ●
RAISE EXCEPTION TYPE [EXPORTING ...] This statement creates a new exception object, which is an instance of class . Optionally, values can be provided for the constructor using the EXPORTING addition.
●
RAISE EXCEPTION This statement uses an existing exception object, namely whichever exception object points to. This exception object is either created directly, using a CREATE OBJECT statement or, more commonly, caught in a previous CATCH ... INTO ... statement and pass explicitly to the caller.
© Copyright. All rights reserved.
361
Unit 8: Class-Based Exceptions
In the example, the constructor catches exception CX_EXC, which is raised by the GET_TECH_ATTR method. The constructor analyzes the exception object, performs necessary adjustments, issues a warning, and so on. The constructor then decides to pass the exception to the main program, where the exception is handled again.
362
© Copyright. All rights reserved.
Unit 8 Exercise 21 Map Exceptions to Each Other
Business Example You want your program to use the class-based exception concept if an invalid plane type is provided when creating an airplane instance. Instead of just propagating the exception raised by GET_TECHNICAL_ATTRIBUTES, the constructor needs to handle it and raise a different exception. You want the two exceptions to be chained together so that the main program can evaluate both. Note: This exercise uses the main program file ZBC401_##_MAIN completed in the previous exercise. If not complete, copy the model solution from the previous exercise. In the exercises for this course, when the input values include ##, replace ## with your group number. Template: SAPBC401_EXC_S1 Solution: SAPBC401_EXC_S2 Handle an Exception Raised by a Method In the constructor of local class LCL_AIRPLANE, handle the exception raised by method GET_TECHNICAL_ATTRIBUTES. 1. Edit the implementation of the constructor of local class LCL_AIRPLANE. Define a local object reference (suggested name: LX_INV_PLANETYPE) and choose its type in such a way that the reference may point to the exception object raised by method GET_TECHNICAL_ATTRIBUTES. 2. Implement a TRY-ENDTRY structure for exception handling. Catch the exception object, but leave the CATCH block empty for now.
Raise and Map a New Exception Raise a new exception and map it to the original one. Adjust the constructor to propagate the new exception to the main program. 1. In the constructor of LCL_AIRPLANE, raise a new exception of TYPE CX_INVALID_VALUE during the handling of the exception raised by GET_TECHNICAL_ATTRIBUTES.
© Copyright. All rights reserved.
363
Unit 8: Class-Based Exceptions
●
Hint: Check the signature of exception class CX_INVALID_VALUE to see if you need to provide values for any attributes it contains. Transfer the reference to the original exception instance to the exception instance constructor. 2. Make sure the instance attribute PREVIOUS of the new exception object points to the already existing exception object. Use import parameter PREVIOUS of the constructor method. 3. Adjust the signature of the constructor so that it propagates the new exception. 4. Which other method signatures do you have to adjust to propagate the exception up to the main program?
Task 3 In the main program, handle the new exception and evaluate the information of both, the new and the original exception instance. 1. Catch your new exception in the main program everytime you create an instance of an airplane. Define a local reference variable for the purpose with a suitable reference type (suggested name: GX_INV_VALUE). 2. Use this reference to extract the text of your new exception. Output the text on the list. 3. Use the same variables to extract the text of the original exception. Output the text on the list.
364
© Copyright. All rights reserved.
Unit 8 Solution 21 Map Exceptions to Each Other
Business Example You want your program to use the class-based exception concept if an invalid plane type is provided when creating an airplane instance. Instead of just propagating the exception raised by GET_TECHNICAL_ATTRIBUTES, the constructor needs to handle it and raise a different exception. You want the two exceptions to be chained together so that the main program can evaluate both. Note: This exercise uses the main program file ZBC401_##_MAIN completed in the previous exercise. If not complete, copy the model solution from the previous exercise. In the exercises for this course, when the input values include ##, replace ## with your group number. Template: SAPBC401_EXC_S1 Solution: SAPBC401_EXC_S2 Handle an Exception Raised by a Method In the constructor of local class LCL_AIRPLANE, handle the exception raised by method GET_TECHNICAL_ATTRIBUTES. 1. Edit the implementation of the constructor of local class LCL_AIRPLANE. Define a local object reference (suggested name: LX_INV_PLANETYPE) and choose its type in such a way that the reference may point to the exception object raised by method GET_TECHNICAL_ATTRIBUTES. a) See the source code extract from the model solution. 2. Implement a TRY-ENDTRY structure for exception handling. Catch the exception object, but leave the CATCH block empty for now. a) See the source code extract from the model solution.
Raise and Map a New Exception Raise a new exception and map it to the original one. Adjust the constructor to propagate the new exception to the main program. 1. In the constructor of LCL_AIRPLANE, raise a new exception of TYPE CX_INVALID_VALUE during the handling of the exception raised by GET_TECHNICAL_ATTRIBUTES.
© Copyright. All rights reserved.
365
Unit 8: Class-Based Exceptions
●
Hint: Check the signature of exception class CX_INVALID_VALUE to see if you need to provide values for any attributes it contains. Transfer the reference to the original exception instance to the exception instance constructor. a) See the source code extract from the model solution. 2. Make sure the instance attribute PREVIOUS of the new exception object points to the already existing exception object. Use import parameter PREVIOUS of the constructor method. a) See the source code extract from the model solution. 3. Adjust the signature of the constructor so that it propagates the new exception. a) See the source code extract from the model solution. 4. Which other method signatures do you have to adjust to propagate the exception up to the main program? The constructors of LCL_CARGO_PLANE and LCL_PASSENGER_PLANE. Task 3 In the main program, handle the new exception and evaluate the information of both, the new and the original exception instance. 1. Catch your new exception in the main program everytime you create an instance of an airplane. Define a local reference variable for the purpose with a suitable reference type (suggested name: GX_INV_VALUE). a) See the source code extract from the model solution. 2. Use this reference to extract the text of your new exception. Output the text on the list. a) See the source code extract from the model solution. 3. Use the same variables to extract the text of the original exception. Output the text on the list. a) See the source code extract from the model solution. Include BC401_EXC_S2_CARRIER *---------------------------------------------------* * CLASS lcl_airplane DEFINITION *---------------------------------------------------* CLASS lcl_airplane DEFINITION. PUBLIC SECTION. METHODS: constructor IMPORTING iv_name TYPE string iv_planetype TYPE saplane-planetype
366
© Copyright. All rights reserved.
Lesson: Implementing Advanced Exception Handling Techniques
RAISING cx_invalid_value, cx_invalid_planetype,
*
display_attributes. CLASS-METHODS: display_n_o_airplanes, class_constructor. EVENTS: airplane_created. PROTECTED SECTION. CONSTANTS: c_pos_1 TYPE i VALUE 30. PRIVATE SECTION. TYPES: ty_planetypes TYPE STANDARD TABLE OF saplane WITH NON-UNIQUE KEY planetype. DATA: mv_name mv_planetype mv_weight mv_tankcap
TYPE TYPE TYPE TYPE
string, saplane-planetype, saplane-weight, saplane-tankcap.
CLASS-DATA: gv_n_o_airplanes TYPE i, gt_planetypes TYPE ty_planetypes. CLASS-METHODS: get_technical_attributes IMPORTING iv_type TYPE saplane-planetype EXPORTING ev_weight TYPE saplane-weight ev_tankcap TYPE saplane-tankcap RAISING cx_invalid_planetype. ENDCLASS.
"lcl_airplane DEFINITION
*-----------------------------------------------* * CLASS lcl_airplane IMPLEMENTATION * *-----------------------------------------------* CLASS lcl_airplane IMPLEMENTATION. METHOD class_constructor. SELECT * FROM saplane INTO TABLE gt_planetypes. ENDMETHOD. "class_constructor METHOD constructor. DATA: lx_inv_planetype TYPE REF TO cx_invalid_planetype. mv_name = iv_name. mv_planetype = iv_planetype.
© Copyright. All rights reserved.
367
Unit 8: Class-Based Exceptions
TRY.
get_technical_attributes( EXPORTING iv_type = iv_planetype IMPORTING ev_weight = mv_weight ev_tankcap = mv_tankcap ).
gv_n_o_airplanes = gv_n_o_airplanes + 1. RAISE EVENT airplane_created. CATCH cx_invalid_planetype INTO lx_inv_planetype. RAISE EXCEPTION TYPE cx_invalid_value EXPORTING parnam = 'IV_PLANETYPE' previous = lx_inv_planetype. ENDTRY. ENDMETHOD.
"constructor
METHOD display_attributes. WRITE: / icon_ws_plane AS ICON, / 'Name of Airplane'(001) , / 'Type of Airplane:'(002), / 'Weight:'(003), LEFT-JUSTIFIED, / 'Tank capacity:'(004), LEFT-JUSTIFIED. ENDMETHOD.
AT c_pos_1 mv_name, AT c_pos_1 mv_planetype, AT c_pos_1 mv_weight AT c_pos_1 mv_tankcap
"display_attributes
METHOD display_n_o_airplanes. SKIP. WRITE: / 'Number of airplanes:'(ca1), AT c_pos_1 gv_n_o_airplanes LEFT-JUSTIFIED. ENDMETHOD. "display_n_o_airplanes METHOD get_technical_attributes. DATA: ls_planetype TYPE saplane. READ TABLE gt_planetypes INTO ls_planetype WITH TABLE KEY planetype = iv_type TRANSPORTING weight tankcap. IF sy-subrc = 0. ev_weight = ls_planetype-weight. ev_tankcap = ls_planetype-tankcap. ELSE. * RAISE wrong_planetype. RAISE EXCEPTION TYPE cx_invalid_planetype EXPORTING planetype = iv_type. ENDIF. ENDMETHOD. "get_technical_attributes ENDCLASS.
"lcl_airplane IMPLEMENTATION
*------------------------------------------------*
368
© Copyright. All rights reserved.
Lesson: Implementing Advanced Exception Handling Techniques
* CLASS lcl_cargo_plane DEFINITION *------------------------------------------------* * *----------------------------------------------------* CLASS lcl_cargo_plane DEFINITION INHERITING FROM lcl_airplane. PUBLIC SECTION.
*
METHODS: constructor IMPORTING iv_name TYPE string iv_planetype TYPE saplane-planetype iv_cargo TYPE s_plan_car RAISING cx_invalid_value, cx_invalid_planetype, display_attributes REDEFINITION. PRIVATE SECTION. DATA: mv_cargo TYPE s_plan_car.
ENDCLASS.
"lcl_cargo_plane DEFINITION
*-------------------------------------------------* * CLASS lcl_cargo_plane IMPLEMENTATION *-------------------------------------------------* CLASS lcl_cargo_plane IMPLEMENTATION. ... ENDCLASS.
"lcl_cargo_plane IMPLEMENTATION
*-------------------------------------------------* * CLASS lcl_passenger_plane DEFINITION *-------------------------------------------------* CLASS lcl_passenger_plane DEFINITION INHERITING FROM lcl_airplane. PUBLIC SECTION.
*
METHODS: constructor IMPORTING iv_name TYPE string iv_planetype TYPE saplane-planetype iv_seats TYPE s_seatsmax RAISING cx_invalid_value, cx_invalid_planetype, display_attributes REDEFINITION. PRIVATE SECTION.
DATA: mv_seats TYPE s_seatsmax. ENDCLASS. "lcl_passenger_plane DEFINITION *------------------------------------------------*
© Copyright. All rights reserved.
369
Unit 8: Class-Based Exceptions
* CLASS lcl_passenger_plane IMPLEMENTATION *------------------------------------------------* CLASS lcl_passenger_plane IMPLEMENTATION. ... ENDCLASS.
"lcl_passenger_plane IMPLEMENTATION
*------------------------------------------------* * CLASS lcl_carrier DEFINITION *------------------------------------------------* CLASS lcl_carrier DEFINITION. ... ENDCLASS. "lcl_carrier DEFINITION *------------------------------------------------* * CLASS lcl_carrier IMPLEMENTATION *------------------------------------------------* CLASS lcl_carrier IMPLEMENTATION. ... ENDCLASS.
"lcl_carrier IMPLEMENTATION
Main Program SAPBC401_EXC_S2 REPORT
sapbc401_exc_s2.
TYPE-POOLS icon. INCLUDE bc401_exc_s2_agency. INCLUDE bc401_exc_s2_carrier. INCLUDE bc401_exc_s2_rental. DATA: go_hotel go_vehicle go_truck go_bus go_rental go_passenger go_cargo go_carrier go_agency
TYPE TYPE TYPE TYPE TYPE TYPE TYPE TYPE TYPE
REF REF REF REF REF REF REF REF REF
TO TO TO TO TO TO TO TO TO
cl_hotel2, lcl_vehicle, lcl_truck, lcl_bus, lcl_rental, lcl_passenger_plane, lcl_cargo_plane, lcl_carrier, lcl_travel_agency.
DATA: gv_text TYPE string, gx_inv_value TYPE REF TO cx_invalid_value. * gx_inv_planetype TYPE REF TO cx_invalid_planetype. START-OF-SELECTION. ******************* ******* create travel_agency CREATE OBJECT go_agency EXPORTING iv_name = 'Travel&Smile Travel'. ******* create hotel CREATE OBJECT go_hotel
370
© Copyright. All rights reserved.
Lesson: Implementing Advanced Exception Handling Techniques
EXPORTING iv_name = 'Sleep Well Hotel' iv_beds = 345. ******* create rental CREATE OBJECT go_rental EXPORTING iv_name = 'Happy Car Rental'. ******* create truck CREATE OBJECT go_truck EXPORTING iv_make = 'MAN' iv_cargo = 45. ******* create truck CREATE OBJECT go_bus EXPORTING iv_make = 'Mercedes' iv_passengers = 80. ******* create truck CREATE OBJECT go_truck EXPORTING iv_make = 'VOLVO' iv_cargo = 48. ***** Create Carrier CREATE OBJECT go_carrier EXPORTING iv_name = 'Smile&Fly'. ***** Passenger Plane TRY. CREATE OBJECT go_passenger EXPORTING iv_name = 'LH BERLIN' iv_planetype = '747-500' iv_seats = 345. CATCH cx_invalid_value INTO gx_inv_value. gv_text = gx_inv_value->get_text( ). WRITE: / icon_failure AS ICON, gv_text. gv_text = gx_inv_value->previous->get_text( ). WRITE: / icon_failure AS ICON, gv_text. * * * * *
CATCH cx_invalid_planetype INTO gx_inv_planetype. gv_text = gx_inv_planetype->get_text( ). WRITE: / icon_failure AS ICON, gv_text. ENDTRY.
***** cargo Plane TRY. CREATE OBJECT go_cargo EXPORTING
© Copyright. All rights reserved.
371
Unit 8: Class-Based Exceptions
iv_name = 'US Hercules' iv_planetype = '747-200F' iv_cargo = 533. CATCH cx_invalid_value INTO gx_inv_value. gv_text = gx_inv_value->get_text( ). WRITE: / icon_failure AS ICON, gv_text. gv_text = gx_inv_value->previous->get_text( ). WRITE: / icon_failure AS ICON, gv_text. * * * * *
CATCH cx_invalid_planetype INTO gx_inv_planetype. gv_text = gx_inv_planetype->get_text( ). WRITE: / icon_failure AS ICON, gv_text. ENDTRY.
***** show attributes of all partners of travel_agency go_agency->display_attributes( ).
372
© Copyright. All rights reserved.
Lesson: Implementing Advanced Exception Handling Techniques
LESSON SUMMARY You should now be able to: ●
Explain the hierarchy of predefined exception classes
●
Explain different ways of handling an exception
●
Retry after exceptions
●
Implement resumable exceptions
●
Map exceptions
© Copyright. All rights reserved.
373
Unit 8: Class-Based Exceptions
374
© Copyright. All rights reserved.
Unit 8 Learning Assessment
1. Which of the following statements is used to raise class-based exceptions? Choose the correct answer. X
A EXPORTING
X
B RAISE EXCEPTION
X
C CREATE OBJECT
X
D CATCH
2. Which of the following blocks is used to catch and handle exceptions? Choose the correct answer. X
A IMPORTING….RETURNING
X
B METHOD…. ENDMETHOD
X
C TRY … ENDTRY
X
D TRY...CATCH...ENDTRY
3. A class-based exception can only be handled if the statement that raised it is enclosed in a TRY-ENDTRY control structure. Determine whether this statement is true or false. X
True
X
False
4. TRY-ENDTRY structures can be nested to any depth. Determine whether this statement is true or false. X
True
X
False
© Copyright. All rights reserved.
375
Unit 8: Learning Assessment
5. You can specify only two exception classes to the CATCH statement. Determine whether this statement is true or false. X
True
X
False
6. If an exception is raised, the name of the exception class is displayed in the __________ field in debugging mode. Choose the correct answer. X
A exception raised
X
B last exception object
X
C watchpoint
X
D layout
7. Which of the following syntax additions is used to propagate an exception from a procedure? Choose the correct answer. X
A CATCH
X
B RAISING
X
C METHODS
X
D FORM
8. For subclasses of ____________ the corresponding exceptions cannot be propagated explicitly using the RAISING addition. Choose the correct answer.
376
X
A CX_STATIC_CHECK
X
B CX_NO_CHECK
X
C CX_DYNAMIC_CHECK
© Copyright. All rights reserved.
Unit 8: Learning Assessment
9. Which of the following are ways of handling an exception? Choose the correct answers. X
A Continue program
X
B Remove the cause of error
X
C Do not propagate an exception
X
D Call method CX_SYSTEM_HANDLE
10. Which of the following is used to jump back to the TRY statement? Choose the correct answer. X
A RETRY
X
B CATCH
X
C TRY-ENTRY
X
D RAISE
11. Which of the following is a prerequisite for using the RESUME statement? Choose the correct answers. X
A The exception has to be caught with addition BEFORE UNWIND.
X
B The exception has to marked resumable.
X
C The exception has to be propagated with addition RESUMABLE( ).
X
D The exception has to be raised with addition RESUMABLE.
© Copyright. All rights reserved.
377
Unit 8 Learning Assessment - Answers
1. Which of the following statements is used to raise class-based exceptions? Choose the correct answer. X
A EXPORTING
X
B RAISE EXCEPTION
X
C CREATE OBJECT
X
D CATCH
2. Which of the following blocks is used to catch and handle exceptions? Choose the correct answer. X
A IMPORTING….RETURNING
X
B METHOD…. ENDMETHOD
X
C TRY … ENDTRY
X
D TRY...CATCH...ENDTRY
3. A class-based exception can only be handled if the statement that raised it is enclosed in a TRY-ENDTRY control structure. Determine whether this statement is true or false. X
True
X
False
4. TRY-ENDTRY structures can be nested to any depth. Determine whether this statement is true or false.
378
X
True
X
False
© Copyright. All rights reserved.
Unit 8: Learning Assessment - Answers
5. You can specify only two exception classes to the CATCH statement. Determine whether this statement is true or false. X
True
X
False
6. If an exception is raised, the name of the exception class is displayed in the __________ field in debugging mode. Choose the correct answer. X
A exception raised
X
B last exception object
X
C watchpoint
X
D layout
Correct. If an exception is raised, the name of the exception class is displayed in the exception raised field in debugging mode. 7. Which of the following syntax additions is used to propagate an exception from a procedure? Choose the correct answer. X
A CATCH
X
B RAISING
X
C METHODS
X
D FORM
8. For subclasses of ____________ the corresponding exceptions cannot be propagated explicitly using the RAISING addition. Choose the correct answer. X
A CX_STATIC_CHECK
X
B CX_NO_CHECK
X
C CX_DYNAMIC_CHECK
© Copyright. All rights reserved.
379
Unit 8: Learning Assessment - Answers
9. Which of the following are ways of handling an exception? Choose the correct answers. X
A Continue program
X
B Remove the cause of error
X
C Do not propagate an exception
X
D Call method CX_SYSTEM_HANDLE
10. Which of the following is used to jump back to the TRY statement? Choose the correct answer. X
A RETRY
X
B CATCH
X
C TRY-ENTRY
X
D RAISE
11. Which of the following is a prerequisite for using the RESUME statement? Choose the correct answers.
380
X
A The exception has to be caught with addition BEFORE UNWIND.
X
B The exception has to marked resumable.
X
C The exception has to be propagated with addition RESUMABLE( ).
X
D The exception has to be raised with addition RESUMABLE.
© Copyright. All rights reserved.
UNIT 9
Object-Oriented Design Patterns
Lesson 1 Implementing Advanced Object-Oriented Techniques
382
Lesson 2 Implementing the Singleton Pattern Exercise 22: Implement the Singleton Pattern
389 393
Lesson 3 Implementing Factory Classes Using Friendship Exercise 23: Implement a Factory Class Using Friendship
402 405
UNIT OBJECTIVES ●
Implement abstract classes
●
Implement final classes
●
Access internal tables with object references
●
Call navigation methods
●
Restrict the visibility of the instance constructor
●
Implement factory methods
●
Implement the singleton pattern
●
Implement friendship relationships
© Copyright. All rights reserved.
381
Unit 9 Lesson 1 Implementing Advanced Object-Oriented Techniques
LESSON OVERVIEW This lesson explains how to implement abstract classes and final classes, how to access internal tables with object references, and how to call the navigation methods. Business Example You need to add special object-oriented programming techniques to your ABAP Objects implementations. For this reason, you require the following knowledge: ●
An understanding of how to define abstract classes
●
An understanding of how to define abstract methods
●
An understanding of how to define final classes
●
An understanding of how to define final methods
●
An understanding of how to use public read-only attributes
●
An understanding of how to call navigational methods
●
An understanding of how to chain functional methods
●
An understanding of how to define the Visibility of the Instance Constructor
LESSON OBJECTIVES After completing this lesson, you will be able to:
382
●
Implement abstract classes
●
Implement final classes
●
Access internal tables with object references
●
Call navigation methods
●
Restrict the visibility of the instance constructor
© Copyright. All rights reserved.
Lesson: Implementing Advanced Object-Oriented Techniques
Abstract Classes
Figure 148: Abstract Classes and Abstract Methods
Abstract class contains both definition and implementation but cannot be instantiated. Use the ABSTRACT addition in the CLASS statement to create an abstract class. Super classes are a typical use for abstract classes, as they are not to be instantiated themselves, but their subclasses are. In an abstract class, you can define abstract methods among other things. This means that the abstract method cannot be implemented in that class. Instead, it is implemented in a subclass of the class. If the subclass of that class is not abstract, the abstract methods must be redefined and implemented in the subclass for the first time.
Note: The relevant indicator is in the Class Builder on the Attributes tab page for that class or method. References to such abstract classes can be used for polymorphic access to subclass instances. Static methods cannot be abstract because they cannot be redefined.
© Copyright. All rights reserved.
383
Unit 9: Object-Oriented Design Patterns
Final Classes
Figure 149: Final Classes and Methods
Prevent a class from being inherited by using the FINAL addition with the class statement. You can prevent a method from being redefined by using the FINAL addition with the methods statement.
Note: The relevant indicator is in the Class Builder on the Attributes tab page for that class or method. Thus, all methods of a final class are implicitly final. You may not repeat the FINAL addition in the methods themselves. Classes that are abstract and final should only contain static components.
Internal Tables with Object References We have learned in a previous section that object references can be stored in internal tables. This is used, in particular, to implement associations. However, we have not yet discussed how we should retrieve a specific object from such a list. The figure Read Access to a Table with Object References, gives an example of how this could be achieved.
384
© Copyright. All rights reserved.
Lesson: Implementing Advanced Object-Oriented Techniques
Figure 150: Read Access to a Table with Object References
Object references can be stored in internal tables. The example in the figure Read Access to a Table with Object References, explains how to retrieve a specific object from such a list. The object reference is stored in the table along with some key information. In the example, the key information is the make and model of the vehicle. The object reference can easily be retrieved through this key information. This technique implies a redundant storage of information as the key values are already stored in attributes of the object. Read Access Using Public Attributes
Figure 151: Read Access Using Public Attributes
© Copyright. All rights reserved.
385
Unit 9: Object-Oriented Design Patterns
As shown in the figure Read Access Using Public Attributes, the key information redundancy can be avoided by making the key attributes public. Public attributes can be used directly in the statements to access internal tables like READ TABLE and LOOP AT. The expression TABE_LINE used here is a built in part of the ABAP language. When the line type of an internal table is an elementary data type instead of a structure type, you need to use TABLE_LINE. Such internal tables have just one unnamed column. TABLE_LINE is used as the generic column name for this single column.
Hint: It is against the fundamental principles of object-oriented programming to make attributes public. Unfortunately, ABAP does not allow you to use functional methods (like the methods in our example GET_MAKE, GET_MODEL, and so on) on the left-hand side of WHERE clauses and WITH KEY additions. Therefore, public attributes are only used in some special cases in read-only mode.
Navigation Methods and Chain Method Calls
Figure 152: Navigation Methods and Chaining of Method Calls
Associations like aggregations and compositions are an important design principle of objectoriented programming. An association means that at runtime, an instance of one class stores references to objects of another class. Classes that have other classes associated with them often come with methods that return one of the stored references to the caller. Such methods are often called navigation methods, as they can be used to navigate from one object to another. In the example, the LCL_VEHICLE class is associated with the LCL_RENTAL class. Class LCL_RENTAL provides the navigation method GET_VEHICLE. Often, the purpose of navigating from one object to another is to access a single method of this other object. We can chain method calls, that is, we can directly call a method of the object that the navigation method returns. This technique is not restricted to the chaining of
386
© Copyright. All rights reserved.
Lesson: Implementing Advanced Object-Oriented Techniques
two methods. In more complicated object models, it is possible to chain any number of methods.
Visibility of the Instance Constructor
Figure 153: Implicit Setting of the Instance Constructor’s Visibility
In ABAP Objects, we can restrict the visibility of the instance constructor. If the visibility of the instance constructor is restricted, the CREATE OBJECT statements to instantiate this class is only allowed in certain parts of the coding. The types of visibilities for the instance constructor are as follows: ●
PRIVATE If a class has a private instance constructor, it can only be instantiated from within the class itself, typically in static methods defined for that purpose. These methods are sometimes called Factory-Methods.
●
PROTECTED If the instance constructor is protected, the visibility is extended to all of its subclasses, that is, the subclasses can also create instances of the class.
●
PUBLIC A public instance constructor is the default visibility setting : Instances of the class can be created anywhere, inside the class itself, inside other classes, or, even in a non-objectoriented part of the program (for example, the main program).
Set the visibility by using the CREATE addition with the CLASS statement.
Note: The relevant indicator is in the Class Builder on the Attributes tab page for the relevant class.
© Copyright. All rights reserved.
387
Unit 9: Object-Oriented Design Patterns
Hint: The visibility of the constructor is not set by placing the definition of the method CONSTRUCTOR in the respective section of the class definition. In fact, before SAP NetWeaver 7.0, it was mandatory to place the constructor syntactically in the public section. Since SAP NetWeaver 7.0, it is allowed, but not required to place the constructor in the protected or private section - if this is not more restrictive than the CREATE… addition in the class definition. This is to increase the readability of the coding.
LESSON SUMMARY You should now be able to:
388
●
Implement abstract classes
●
Implement final classes
●
Access internal tables with object references
●
Call navigation methods
●
Restrict the visibility of the instance constructor
© Copyright. All rights reserved.
Unit 9 Lesson 2 Implementing the Singleton Pattern
LESSON OVERVIEW This lesson explains the concepts of factory methods, the singleton pattern, and their implementation. Business Example: You need to add special object-oriented programming techniques to your ABAP Objects implementations. For this reason, you require the following knowledge: ●
An understanding of factory method
●
An understanding of singleton pattern
LESSON OBJECTIVES After completing this lesson, you will be able to: ●
Implement factory methods
●
Implement the singleton pattern
Factory Methods Restricting the visibility of the instance constructor only makes sense if somewhere within the class (or its subclasses, in case of CREATE PROTECTED) the instantiation is done. Often, such classes provide a public static method that creates an instance of this class and returns the reference to this instance to the caller. Such methods are sometimes called factory methods. Factory methods are executed when a instance of the class is created and has some advantages as compared to the instance constructor. Some advantages of factory methods are as follows: ●
A factory method can have coding that executes before the actual instantiation. For example, the method can perform checks, read data from the database, or set locks, before actually creating the instance. If an error occurs, no instance is created; and, no memory is allocated for it.
●
Classes can have more than one factory method. Each of the methods can have a different implementation and signature as well. The different factory method makes it possible to create instances of the same class based on different information. For example, one factory method creates a new instance that offers input parameters for all attributes, while another factory method only imports key information and then retrieve the other attribute values from the database.
●
Use factory methods to administrate the instances of a class within the class itself.
© Copyright. All rights reserved.
389
Unit 9: Object-Oriented Design Patterns
The administration of the instance within the class is often used to avoid the creation of many identical instances. A reference of every new instance is stored in a private static attribute of the class (an internal table). Whenever the factory method is called, it first checks whether an instance with this key already exists. If so, it returns the existing instance instead of creating a new one. ●
Use a factory method to instantiate one of the subclasses rather than the class itself. As an example, the factory method of an airplane class can check the plane type, then instantiate either a cargo or a passenger plane.
Example for a Class with Factory Method
Figure 154: Example for a Class with Factory Method
The example illustrates a class with a Factory Method and using a static attribute to reference all its instances. The instantiation is restricted to the class and is only done in static method FACTORY. When the method is called, the factory method checks whether an identical instance has already been created. If so, it returns the existing instance instead of creating a new one.
Hint: In this example, it is not necessary to make attributes public for the READ TABLE statement. As the factory method lies within the class, it has full access to all private attributes.
390
© Copyright. All rights reserved.
Lesson: Implementing the Singleton Pattern
The Singleton Pattern
Figure 155: Singleton Class - Using a Factory Method
Use the singleton concept to prevent a class from being instantiated more than once for the same program context. There are various different ways to implement a singleton class. The first singleton pattern is a special case of the factory concept. Instead of storing several instances, the class stores only one instance. When the factory method GET_INSTANCE is called for the first time, it instantiates the class. For every subsequent call, it returns the reference to the existing object.
© Copyright. All rights reserved.
391
Unit 9: Object-Oriented Design Patterns
Singleton Class - Using the Static Constructor
Figure 156: Singleton Class - Using the Static Constructor
The class uses its static constructor to create the single instance in advance. The GET_INSTANCE method does not create the instance but only returns a reference to the already existing instance. Hint: In a third variant of the singleton pattern, the GO_INSTANCE static attribute is made public and read-only. The GET_INSTANCE method is not required.
392
© Copyright. All rights reserved.
Unit 9 Exercise 22 Implement the Singleton Pattern
Business Example To improve the robustness of your application, you need to create two kinds of airplanes (passenger and cargo), implement them as final classes so they are not further specialized. Only specific airplanes are created and the travel agency can only be instantiated once. Note: This exercise uses the main program file ZBC401_##_MAIN completed in the previous exercise. If not complete, copy the model solution from the previous exercise. In the exercises for this course, when the input values include ##, replace ## with your group number. Template: SAPBC401_GCL_S2 Solution: SAPBC401_SPC_S1 Use the Techniques of ABAP Objects to Avoid Further Specialization Use the techniques of ABAP Objects to avoid the further specialization of passenger and cargo planes. 1. Declare classes LCL_PASSENGER_PLANE and LCL_CARGO_PLANE as FINAL class. 2. What happens if you declare class LCL_AIRPLANE as FINAL class ?
3. What would happen if you make method DISPLAY_ATTRIBUTES in class LCL_AIRPLANE a final method?
Use the Techniques of ABAP Objects to inhibit the Instantiation of a Class Use the techniques of ABAP Objects to inhibit the instantiation of class LCL_AIRPLANE. 1. Declare LCL_AIRPLANE as an abstract class.
© Copyright. All rights reserved.
393
Unit 9: Object-Oriented Design Patterns
2. Prove that it is not allowed to instantiate the class itself. In your main program, declare a reference variable TYPE REF TO lcl_airplane and implement a CREATE OBJECT statement for it. After the syntax check, remove the CREATE OBJECT statement. Implement a Singleton Pattern Make sure the LCL_TRAVEL_AGENCY class can only be instantiated once in your program. Implement one of the singleton patterns discussed in the course. 1. Restrict the visibility of the instance constructor and inhibit any inheritance from the class. 2. Define a static attribute to store a reference to the one instance there. Depending on the pattern you implement, make it private or public and read-only. 3. Depending on the pattern you implement, define and implement a static constructor and/or a GET_INSTANCE method. Implement the instantiation of the class according to the singleton pattern. 4. Adjust the main program. Remove the CREATE OBJECT statement for the travel agency from the main program. Depending on the single pattern you implemented, replace it with a call of the GET_INSTANCE method or with an access to the public attribute. 5. Optional-If you have implemented a pattern that includes a GET_INSTANCE method, use a method chain to retrieve the singleton instance and call its DISPLAY_ATTRIBUTE method in one statement.
394
© Copyright. All rights reserved.
Unit 9 Solution 22 Implement the Singleton Pattern
Business Example To improve the robustness of your application, you need to create two kinds of airplanes (passenger and cargo), implement them as final classes so they are not further specialized. Only specific airplanes are created and the travel agency can only be instantiated once. Note: This exercise uses the main program file ZBC401_##_MAIN completed in the previous exercise. If not complete, copy the model solution from the previous exercise. In the exercises for this course, when the input values include ##, replace ## with your group number. Template: SAPBC401_GCL_S2 Solution: SAPBC401_SPC_S1 Use the Techniques of ABAP Objects to Avoid Further Specialization Use the techniques of ABAP Objects to avoid the further specialization of passenger and cargo planes. 1. Declare classes LCL_PASSENGER_PLANE and LCL_CARGO_PLANE as FINAL class. a) See the source code extract from the model solution. 2. What happens if you declare class LCL_AIRPLANE as FINAL class ? This results in a syntax error as classes LCL_PASSENGER_PLANE already inherited from this class.
LCL_CARGO_PLANE
and
3. What would happen if you make method DISPLAY_ATTRIBUTES in class LCL_AIRPLANE a final method? This results in a syntax error as the method is already redefined in classes LCL_CARGO_PLANE and LCL_PASSENGER_PLANE.
Use the Techniques of ABAP Objects to inhibit the Instantiation of a Class Use the techniques of ABAP Objects to inhibit the instantiation of class LCL_AIRPLANE. 1. Declare LCL_AIRPLANE as an abstract class.
© Copyright. All rights reserved.
395
Unit 9: Object-Oriented Design Patterns
a) See the source code extract from the model solution. 2. Prove that it is not allowed to instantiate the class itself. In your main program, declare a reference variable TYPE REF TO lcl_airplane and implement a CREATE OBJECT statement for it. After the syntax check, remove the CREATE OBJECT statement. a) Carry out this step in the usual manner. Implement a Singleton Pattern Make sure the LCL_TRAVEL_AGENCY class can only be instantiated once in your program. Implement one of the singleton patterns discussed in the course. 1. Restrict the visibility of the instance constructor and inhibit any inheritance from the class. a) Use the FINAL and CREATE PRIVATE additions to the CLASS ... DEFINITION statement. Optionally, move the definition of the instance constructor to the private section. See the source code extract from the model solution. 2. Define a static attribute to store a reference to the one instance there. Depending on the pattern you implement, make it private or public and read-only. a) See the source code extract from the model solution. 3. Depending on the pattern you implement, define and implement a static constructor and/or a GET_INSTANCE method. Implement the instantiation of the class according to the singleton pattern. a) See the source code extract from the model solution. 4. Adjust the main program. Remove the CREATE OBJECT statement for the travel agency from the main program. Depending on the single pattern you implemented, replace it with a call of the GET_INSTANCE method or with an access to the public attribute. a) See the source code extract from the model solution. 5. Optional-If you have implemented a pattern that includes a GET_INSTANCE method, use a method chain to retrieve the singleton instance and call its DISPLAY_ATTRIBUTE method in one statement. a) See the source code extract from the model solution. Solution: Include BC401_SPC_S1_CARRIER *------------------------------------------------* * CLASS lcl_airplane DEFINITION *------------------------------------------------* CLASS lcl_airplane DEFINITION ABSTRACT. ... ENDCLASS. "lcl_airplane DEFINITION *------------------------------------------------* * CLASS lcl_airplane IMPLEMENTATION *------------------------------------------------* CLASS lcl_airplane IMPLEMENTATION. ... ENDCLASS. "lcl_airplane IMPLEMENTATION *------------------------------------------------* * CLASS lcl_cargo_plane DEFINITION *------------------------------------------------* CLASS lcl_cargo_plane DEFINITION INHERITING FROM lcl_airplane FINAL.
396
© Copyright. All rights reserved.
Lesson: Implementing the Singleton Pattern
... ENDCLASS.
"lcl_cargo_plane DEFINITION
*------------------------------------------------* * CLASS lcl_cargo_plane IMPLEMENTATION *------------------------------------------------* CLASS lcl_cargo_plane IMPLEMENTATION. ... ENDCLASS. "lcl_cargo_plane IMPLEMENTATION *------------------------------------------------* * CLASS lcl_passenger_plane DEFINITION *------------------------------------------------* CLASS lcl_passenger_plane DEFINITION INHERITING FROM lcl_airplane FINAL. ... ENDCLASS. "lcl_passenger_plane DEFINITION *------------------------------------------------* * CLASS lcl_passenger_plane IMPLEMENTATION *------------------------------------------------* CLASS lcl_passenger_plane IMPLEMENTATION. ... ENDCLASS. "lcl_passenger_plane IMPLEMENTATION Include BC401_SPC_S1_AGENCY *-------------------------------------------------* * CLASS lcl_travel_agency DEFINITION *-------------------------------------------------* CLASS lcl_travel_agency DEFINITION FINAL CREATE PRIVATE. PUBLIC SECTION. CLASS-METHODS: get_instance RETURNING value(ro_instance) TYPE REF TO lcl_travel_agency. METHODS: display_agency_partners, display_attributes. PRIVATE SECTION. DATA: mv_name TYPE string, mt_partners TYPE TABLE OF REF TO if_partner. CLASS-DATA: go_instance TYPE REF TO lcl_travel_agency. METHODS: constructor IMPORTING iv_name TYPE string. METHODS: on_partner_created FOR EVENT partner_created OF if_partner IMPORTING sender. ENDCLASS.
© Copyright. All rights reserved.
"lcl_travel_agency DEFINITION
397
Unit 9: Object-Oriented Design Patterns
*---------------------------------------------------* * CLASS lcl_travel_agency IMPLEMENTATION *---------------------------------------------------* CLASS lcl_travel_agency IMPLEMENTATION. METHOD get_instance. IF go_instance IS NOT BOUND. CREATE OBJECT go_instance EXPORTING iv_name = 'Travel&Smile Travel'. ENDIF. ro_instance = go_instance. ENDMETHOD. "get_instance METHOD display_attributes. WRITE: / icon_private_files AS ICON, 'Travel Agency:'(007), mv_name. SKIP. display_agency_partners( ). ENDMETHOD. "display_attributes METHOD display_agency_partners. DATA: lo_partner TYPE REF TO if_partner. WRITE 'Here are the partners of the travel agency:'(008). ULINE. LOOP AT mt_partners INTO lo_partner. lo_partner->display_partner( ). ENDLOOP. ENDMETHOD. "display_agency_partners METHOD constructor. mv_name = iv_name. SET HANDLER on_partner_created FOR ALL INSTANCES. ENDMETHOD. "constructor METHOD on_partner_created. APPEND sender TO mt_partners. ENDMETHOD. "on_partner_created ENDCLASS. Main Program SAPBC401_SPC_S1 REPORT
sapbc401_spc_s1.
TYPE-POOLS icon. INCLUDE bc401_spc_s1_agency. INCLUDE bc401_spc_s1_carrier. INCLUDE bc401_spc_s1_rental. DATA: go_hotel go_agency go_vehicle go_truck go_bus go_rental go_passenger go_cargo
398
TYPE TYPE TYPE TYPE TYPE TYPE TYPE TYPE
REF REF REF REF REF REF REF REF
TO TO TO TO TO TO TO TO
cl_hotel2, lcl_travel_agency, lcl_vehicle, lcl_truck, lcl_bus, lcl_rental, lcl_passenger_plane, lcl_cargo_plane,
© Copyright. All rights reserved.
Lesson: Implementing the Singleton Pattern
go_carrier
TYPE REF TO lcl_carrier.
START-OF-SELECTION. ******************* ******* create travel_agency *********************** * CREATE OBJECT go_agency * EXPORTING * iv_name = 'Travel&Smile Travel'. go_agency = lcl_travel_agency=>get_instance( ). ******* create hotel ******************************* CREATE OBJECT go_hotel EXPORTING iv_name = 'Sleep Well Hotel' iv_beds = 345. ******* create rental ******************************* CREATE OBJECT go_rental EXPORTING iv_name = 'Happy Car Rental'. ******* create truck ********************************* CREATE OBJECT go_truck EXPORTING iv_make = 'MAN' iv_cargo = 45. ******* create truck ********************************* CREATE OBJECT go_bus EXPORTING iv_make = 'Mercedes' iv_passengers = 80. ******* create truck ********************************* CREATE OBJECT go_truck EXPORTING iv_make = 'VOLVO' iv_cargo = 48. ***** Create Carrier ********************************* CREATE OBJECT go_carrier EXPORTING iv_name = 'Smile&Fly Travel'. ***** Passenger Plane ******************************** CREATE OBJECT go_passenger EXPORTING iv_name = 'LH BERLIN' iv_planetype = '747-400' iv_seats = 345 EXCEPTIONS wrong_planetype = 1. IF sy-subrc <> 0. WRITE: / icon_failure AS ICON, 'Wrong plane type'. ENDIF. ***** cargo Plane ************************************
© Copyright. All rights reserved.
399
Unit 9: Object-Oriented Design Patterns
CREATE OBJECT go_cargo EXPORTING iv_name = 'US Hercules' iv_planetype = '747-200F' iv_cargo = 533 EXCEPTIONS wrong_planetype = 1. IF sy-subrc <> 0. WRITE: / icon_failure AS ICON, 'Wrong plane type'. ENDIF. ***** show attributes of all partners of travel_agency go_agency->display_attributes( ). * Optional part: Use method chain: * * lcl_travel_agency=>get_instance( )->display_attributes( ).
400
© Copyright. All rights reserved.
Lesson: Implementing the Singleton Pattern
LESSON SUMMARY You should now be able to: ●
Implement factory methods
●
Implement the singleton pattern
© Copyright. All rights reserved.
401
Unit 9 Lesson 3 Implementing Factory Classes Using Friendship
LESSON OVERVIEW This lesson explains the method of implementing factory classes using friendship. Business Example As a developer create a factory class for airplanes using friendship. For this reason, you require the following knowledge: ●
An understanding of the definition of friendship relationships
●
An understanding of friendship and inheritance
●
An understanding of the implementation of factory classes
LESSON OBJECTIVES After completing this lesson, you will be able to: ●
Implement friendship relationships
Definition of Friendship Relationships
Figure 157: Definition of a Friendship Relationship Between Classes
In some cases, classes have to work together so closely that one class needs access to the other classes protected and private components. Similarly, one class might need to be able to create instances of the other class regardless of the visibility of the constructor. To avoid
402
© Copyright. All rights reserved.
Lesson: Implementing Factory Classes Using Friendship
making these options available to all users of the class, use the concept of class friendship. A class can grant friendship to other classes and interfaces and, hence, to all classes that implement the interface. To create friendship, use the FRIENDS addition of the CLASS statement or the FRIENDS tab page in the Class Builder. All classes and interfaces to which friendship is granted are listed there. Granting friendship is one direction. A class granting friendship is not automatically a friend of the classes’ friends. If a class granting friendship wants to access the non-public components of a friend, this friend must also explicitly grant friendship to it.
Implementation of Factory Classes
Figure 158: Example of a Factory Class
A typical application of the friends concept is the definition of a factory class. Like the factory method, a factory class creates and administrates the instances of a class. By outsourcing the administration to a dedicated class, the class itself is kept smaller and easier to understand. In the example, LCL_FACTORY serves as a factory class for airplanes. LCL_FACTORY class provides a public method CREATE_AIRPLANE in which CREATE_AIRPLANE either instantiates class LCL_AIRPLANE or returns a reference to an already existing instance. To restrict the instantiation, class LCL_AIRPLANE is defined with addition CREATE PRIVATE. By adding FRIENDS LCL_FACTORY, the friendship allows the factory class and only the factory class to create airplane instances and to access the private attributes.
© Copyright. All rights reserved.
403
Unit 9: Object-Oriented Design Patterns
Hint: Another advantage of the dedicated factory class is that if the class has subclasses, the decision on which of the classes should be instantiated could be done inside the factory class rather than by the calling program. In the example, the CREATE_AIRPLANE method could create and return an instance of either LCL_CARGO_PLANE or LCL_PASSENGER_PLANE depending on the plane type.
Friendship and Inheritance The friend attribute is inherited. Classes that inherit from friends and interfaces containing a friend as a component interface, also become friends. Therefore, we advise that extreme caution must be taken when granting friendship. The higher up a friend is in the inheritance tree, the more subclasses can access all components of a class that grants friendship. Conversely, granting friendship is not inherited. A friend of a superclass is, therefore, not automatically a friend of its subclasses.
404
© Copyright. All rights reserved.
Unit 9 Exercise 23 Implement a Factory Class Using Friendship
Business Example Instead of instantiating airplane objects in the main program directly, create airplanes by using a factory class. The factory class should provide one single factory method. Depending on the input, the factory class decides inside this factory method, whether to create a cargo plane or a passenger plane. Note: This exercise uses the main program file ZBC401_##_MAIN completed in the previous exercise. If not complete, copy the model solution from the previous exercise. In the exercises for this course, when the input values include ##, replace ## with your group number. Template: SAPBC401_SPC_S1 Solution: SAPBC401_ SPC_S2 Define a Factory Class In your program, define a factory class (suggested name: LCL_AIRPLANE_FACTORY) with a public static factory method for airplanes (suggested name: CREATE_AIRPLANE). The factory method should have suitably typed import parameters for name, plane type, cargo, and seats. The factory method for import parameters cargo and seats can be optional. It should also have a single returning parameter to return a reference to an airplane instance – either a cargo plane or a passenger plane. 1. Edit the include, which contains the classes for airplanes. Add the definition of the new class there. 2. Within the class, define a public static factory method for airplanes. Define four import parameters for name, plane type, cargo, and seats. Name and type them exactly as in the constructors of your airplane classes. Make the parameters for cargo and seats optional. Hint: Use addition OPTIONAL to do so.
3. Define a returning parameter (suggested name: RO_AIRPLANE). How do you have to type the parameter so that the method can return a reference to either a cargo plane instance or a passenger plane instance?
© Copyright. All rights reserved.
405
Unit 9: Object-Oriented Design Patterns
Implement a Factory Method Implement the factory method. Depending on the optional parameter that is supplied, create either a cargo plane instance or a passenger plane instance. Define a suitable exception and raise it if both optional parameters are supplied or none of them. 1. In the factory method, define two local reference variables. Type one with the class for cargo planes (LCL_CARGO_PLANE) and one with the class for passenger planes (LCL_PASSENGER_PLANE). 2. Implement an IF-structure in which you analyze the content of the import parameters for cargo and seats. Create either an instance of the cargo plane class or the passenger plane class. In the case of success, move the reference to the new object to the returning parameter. 3. In the definition of the factory class, add two exceptions. One that you raise if a wrong plane type was specified (suggested name: WRONG_PLANETYPE), and one that you raise if both or none of the optional parameters were supplied (suggested name: WRONG_PARAM_COMBINATION). Restrict Object Creation to Factory Classes Restrict the creation of cargo planes and passenger planes so that they can only be created from inside the factory class. 1. Use the CREATE PRIVATE addition to restrict the instantiation of the classes for cargo planes and passenger planes. Optionally, move the constructor definitions of both classes to the private section. 2. Use the FRIENDS addition to allow the instantiation of the classes for cargo planes and passenger planes from inside the factory class. Hint: You have to use statement CLASS... DEFINITION DEFERRED before the definition of the airplane classes. Otherwise, the factory class or at least its name, is not known to the syntax check when it reaches the FRIENDS addition.
Replace Direct Instantiations by Calls of the Factory Method Adjust your main program. Remove the direct instantiations of airplanes and replace them by calls of the factory method. 1. Replace the instantiations of airplanes with calls of the factory method. Hint: If you have used exactly the same parameter names as in the constructors, you can keep the parameter passing.
406
© Copyright. All rights reserved.
Lesson: Implementing Factory Classes Using Friendship
2. Do you have to actually receive the references to the new objects?
3. Save, check activate, test, and debug your program.
© Copyright. All rights reserved.
407
Unit 9 Solution 23 Implement a Factory Class Using Friendship
Business Example Instead of instantiating airplane objects in the main program directly, create airplanes by using a factory class. The factory class should provide one single factory method. Depending on the input, the factory class decides inside this factory method, whether to create a cargo plane or a passenger plane. Note: This exercise uses the main program file ZBC401_##_MAIN completed in the previous exercise. If not complete, copy the model solution from the previous exercise. In the exercises for this course, when the input values include ##, replace ## with your group number. Template: SAPBC401_SPC_S1 Solution: SAPBC401_ SPC_S2 Define a Factory Class In your program, define a factory class (suggested name: LCL_AIRPLANE_FACTORY) with a public static factory method for airplanes (suggested name: CREATE_AIRPLANE). The factory method should have suitably typed import parameters for name, plane type, cargo, and seats. The factory method for import parameters cargo and seats can be optional. It should also have a single returning parameter to return a reference to an airplane instance – either a cargo plane or a passenger plane. 1. Edit the include, which contains the classes for airplanes. Add the definition of the new class there. a) Refer the source text excerpt from the model solution. 2. Within the class, define a public static factory method for airplanes. Define four import parameters for name, plane type, cargo, and seats. Name and type them exactly as in the constructors of your airplane classes. Make the parameters for cargo and seats optional. Hint: Use addition OPTIONAL to do so.
a) Refer the source text excerpt from the model solution.
408
© Copyright. All rights reserved.
Lesson: Implementing Factory Classes Using Friendship
3. Define a returning parameter (suggested name: RO_AIRPLANE). How do you have to type the parameter so that the method can return a reference to either a cargo plane instance or a passenger plane instance? a) You have to type the parameter with the common superclass of cargo planes and passenger planes, that is, TYPE REF TO lcl_airplane. Refer the source text excerpt from the model solution.
Implement a Factory Method Implement the factory method. Depending on the optional parameter that is supplied, create either a cargo plane instance or a passenger plane instance. Define a suitable exception and raise it if both optional parameters are supplied or none of them. 1. In the factory method, define two local reference variables. Type one with the class for cargo planes (LCL_CARGO_PLANE) and one with the class for passenger planes (LCL_PASSENGER_PLANE). a) Refer the source text excerpt from the model solution. 2. Implement an IF-structure in which you analyze the content of the import parameters for cargo and seats. Create either an instance of the cargo plane class or the passenger plane class. In the case of success, move the reference to the new object to the returning parameter. a) Refer the source text excerpt from the model solution. 3. In the definition of the factory class, add two exceptions. One that you raise if a wrong plane type was specified (suggested name: WRONG_PLANETYPE), and one that you raise if both or none of the optional parameters were supplied (suggested name: WRONG_PARAM_COMBINATION). a) Refer the source text excerpt from the model solution. Restrict Object Creation to Factory Classes Restrict the creation of cargo planes and passenger planes so that they can only be created from inside the factory class. 1. Use the CREATE PRIVATE addition to restrict the instantiation of the classes for cargo planes and passenger planes. Optionally, move the constructor definitions of both classes to the private section. a) Refer the source text excerpt from the model solution. 2. Use the FRIENDS addition to allow the instantiation of the classes for cargo planes and passenger planes from inside the factory class. Hint: You have to use statement CLASS... DEFINITION DEFERRED before the definition of the airplane classes. Otherwise, the factory class or at least its name, is not known to the syntax check when it reaches the FRIENDS addition. a) Refer the source text excerpt from the model solution. Replace Direct Instantiations by Calls of the Factory Method
© Copyright. All rights reserved.
409
Unit 9: Object-Oriented Design Patterns
Adjust your main program. Remove the direct instantiations of airplanes and replace them by calls of the factory method. 1. Replace the instantiations of airplanes with calls of the factory method. Hint: If you have used exactly the same parameter names as in the constructors, you can keep the parameter passing. a) Refer the source text excerpt from the model solution. 2. Do you have to actually receive the references to the new objects? No. Through the message handling implemented earlier, the carrier instance takes care of all new airplane instances and aggregates them. 3. Save, check activate, test, and debug your program. a) Save your program. b) To check your program, on the application toolbar choose the Check button. c) To activate your program, on the application toolbar choose the Activate button. d) To test your program, on the application toolbar choose the Direct Processing button. e) To debug the program, on the application toolbar choose Execute, or press F8. Include BC401_SPC_S2_CARRIER CLASS lcl_airplane_factory DEFINITION DEFERRED. *----------------------------------------------------* * CLASS lcl_airplane DEFINITION * *----------------------------------------------------* CLASS lcl_airplane DEFINITION ABSTRACT. ... ENDCLASS. "lcl_airplane DEFINITION *-----------------------------------------------------* * CLASS lcl_airplane IMPLEMENTATION * *-----------------------------------------------------* CLASS lcl_airplane IMPLEMENTATION. ... ENDCLASS. "lcl_airplane IMPLEMENTATION *-----------------------------------------------------* * CLASS lcl_cargo_plane DEFINITION *-----------------------------------------------------* * *-----------------------------------------------------* CLASS lcl_cargo_plane DEFINITION INHERITING FROM lcl_airplane FINAL
410
© Copyright. All rights reserved.
Lesson: Implementing Factory Classes Using Friendship
CREATE PRIVATE FRIENDS lcl_airplane_factory. ... ENDCLASS. "lcl_cargo_plane DEFINITION *-----------------------------------------------------* * CLASS lcl_cargo_plane IMPLEMENTATION *-----------------------------------------------------* CLASS lcl_cargo_plane IMPLEMENTATION. ... ENDCLASS. "lcl_cargo_plane IMPLEMENTATION *-----------------------------------------------------* * CLASS lcl_passenger_plane DEFINITION *-----------------------------------------------------* CLASS lcl_passenger_plane DEFINITION INHERITING FROM lcl_airplane FINAL CREATE PRIVATE FRIENDS lcl_airplane_factory. ... ENDCLASS. "lcl_passenger_plane DEFINITION *---------------------------------------------------* * CLASS lcl_passenger_plane IMPLEMENTATION *---------------------------------------------------* CLASS lcl_passenger_plane IMPLEMENTATION. ... ENDCLASS. "lcl_passenger_plane IMPLEMENTATION *--------------------------------------------------* * CLASS lcl_carrier DEFINITION *--------------------------------------------------* CLASS lcl_carrier DEFINITION. ... ENDCLASS. "lcl_carrier DEFINITION *--------------------------------------------------* * CLASS lcl_carrier IMPLEMENTATION *--------------------------------------------------* CLASS lcl_carrier IMPLEMENTATION. ... ENDCLASS.
"lcl_carrier IMPLEMENTATION
*--------------------------------------------------* * CLASS lcl_airplane_factory DEFINITION *--------------------------------------------------* CLASS lcl_airplane_factory DEFINITION. PUBLIC SECTION. CLASS-METHODS: create_airplane IMPORTING iv_name
© Copyright. All rights reserved.
TYPE string
411
Unit 9: Object-Oriented Design Patterns
iv_planetype TYPE saplane-planetype iv_cargo TYPE s_plan_car OPTIONAL iv_seats TYPE s_seatsmax OPTIONAL RETURNING value(ro_airplane) TYPE REF TO lcl_airplane EXCEPTIONS wrong_planetype wrong_param_combination. ENDCLASS. "lcl_airplane_factory DEFINITION *--------------------------------------------------* * CLASS lcl_airplane_factory IMPLEMENTATION *--------------------------------------------------* CLASS lcl_airplane_factory IMPLEMENTATION. METHOD create_airplane. DATA: lo_cargo TYPE REF TO lcl_cargo_plane, lo_passenger TYPE REF TO lcl_passenger_plane. IF iv_cargo IS NOT INITIAL AND iv_seats IS INITIAL. CREATE OBJECT lo_cargo EXPORTING iv_name = iv_name iv_planetype = iv_planetype iv_cargo = iv_cargo EXCEPTIONS wrong_planetype = 1. IF sy-subrc <> 0. RAISE wrong_planetype. ELSE. ro_airplane = lo_cargo. ENDIF. ELSEIF iv_cargo IS INITIAL AND iv_seats IS NOT INITIAL. CREATE OBJECT lo_passenger EXPORTING iv_name = iv_name iv_planetype = iv_planetype iv_seats = iv_seats EXCEPTIONS wrong_planetype = 1. IF sy-subrc <> 0. RAISE wrong_planetype. ELSE. ro_airplane = lo_passenger. ENDIF. ELSE. RAISE wrong_param_combination. ENDIF. ENDMETHOD. ENDCLASS.
"create_airplane "lcl_airplane_factory IMPLEMENTATION
SAPBC401_SPC_S2 REPORT
412
sapbc401_spc_s2.
© Copyright. All rights reserved.
Lesson: Implementing Factory Classes Using Friendship
TYPE-POOLS icon. INCLUDE bc401_spc_s2_agency. INCLUDE bc401_spc_s2_carrier. INCLUDE bc401_spc_s2_rental. DATA: go_agency TYPE REF TO lcl_travel_agency, go_hotel TYPE REF TO cl_hotel2, go_vehicle TYPE REF TO lcl_vehicle, go_truck TYPE REF TO lcl_truck, go_bus TYPE REF TO lcl_bus, go_rental TYPE REF TO lcl_rental, *go_passenger TYPE REF TO lcl_passenger_plane, *go_cargo TYPE REF TO lcl_cargo_plane, go_carrier TYPE REF TO lcl_carrier. START-OF-SELECTION. ******************* ******* create travel_agency *********************** * CREATE OBJECT go_agency * EXPORTING * iv_name = 'Travel&Smile Travel'. go_agency = lcl_travel_agency=>get_instance( ). ******* create hotel ******************************* CREATE OBJECT go_hotel EXPORTING iv_name = 'Sleep Well Hotel' iv_beds = 345. ******* create rental ****************************** CREATE OBJECT go_rental EXPORTING iv_name = 'Happy Car Rental'. ******* create truck ******************************* CREATE OBJECT go_truck EXPORTING iv_make = 'MAN' iv_cargo = 45. ******* create truck ******************************* CREATE OBJECT go_bus EXPORTING iv_make = 'Mercedes' iv_passengers = 80. ******* create truck ******************************* CREATE OBJECT go_truck EXPORTING iv_make = 'VOLVO' iv_cargo = 48. ***** Create Carrier ******************************* CREATE OBJECT go_carrier EXPORTING iv_name = 'Smile&Fly-Travel'. ***** Passenger Plane ******************************
© Copyright. All rights reserved.
413
Unit 9: Object-Oriented Design Patterns
lcl_airplane_factory=>create_airplane( EXPORTING iv_name = 'LH BERLIN' iv_planetype = '747-400' iv_seats = 345 EXCEPTIONS wrong_planetype = 1 wrong_param_combination = 2 ). IF sy-subrc = 1. WRITE: / icon_failure AS ICON, 'Wrong plane type'. ENDIF. ***** cargo Plane ********************************** lcl_airplane_factory=>create_airplane( EXPORTING iv_name = 'US Hercules' iv_planetype = '747-200F' iv_cargo = 533 EXCEPTIONS wrong_planetype = 1 wrong_param_combination = 2 ). IF sy-subrc = 1. WRITE: / icon_failure AS ICON, 'Wrong plane type'. ENDIF. ***** show attributes of all partners of travel_agency go_agency->display_attributes( ).
414
© Copyright. All rights reserved.
Lesson: Implementing Factory Classes Using Friendship
LESSON SUMMARY You should now be able to: ●
Implement friendship relationships
© Copyright. All rights reserved.
415
Unit 9: Object-Oriented Design Patterns
416
© Copyright. All rights reserved.
Unit 9 Learning Assessment
1. Static _____________ cannot be abstract because they cannot be redefined. Choose the correct answer. X
A classes
X
B structures
X
C methods
X
D attributes
2. You can prevent a class from being inherited from by defining it as final. Determine whether this statement is true or false. X
True
X
False
3. An association means that at runtime an instance of one class stores references to objects of another class. Determine whether this statement is true or false. X
True
X
False
4. If the visibility of the instance constructor is changed from private to protected, the visibility is extended to all of its subclasses. Determine whether this statement is true or false. X
True
X
False
© Copyright. All rights reserved.
417
Unit 9: Learning Assessment
5. Which of the following are the advantages of a factory method? Choose the correct answers. X
A A factory method can have coding that is executed before the actual instantiation.
X
B A class can have more than one factory method with different implementations and signatures.
X
C Factory methods cannot be used to administrate the instances of a class within the class itself.
X
D A factory method cannot be used to instantiate one of the subclasses rather than the class itself.
6. Which of the following concepts is used to provide a class access to the private components of the other class? Choose the correct answer.
418
X
A Singleton
X
B Friendship
X
C Interface
X
D Casting
© Copyright. All rights reserved.
Unit 9 Learning Assessment - Answers
1. Static _____________ cannot be abstract because they cannot be redefined. Choose the correct answer. X
A classes
X
B structures
X
C methods
X
D attributes
2. You can prevent a class from being inherited from by defining it as final. Determine whether this statement is true or false. X
True
X
False
3. An association means that at runtime an instance of one class stores references to objects of another class. Determine whether this statement is true or false. X
True
X
False
4. If the visibility of the instance constructor is changed from private to protected, the visibility is extended to all of its subclasses. Determine whether this statement is true or false. X
True
X
False
© Copyright. All rights reserved.
419
Unit 9: Learning Assessment - Answers
5. Which of the following are the advantages of a factory method? Choose the correct answers. X
A A factory method can have coding that is executed before the actual instantiation.
X
B A class can have more than one factory method with different implementations and signatures.
X
C Factory methods cannot be used to administrate the instances of a class within the class itself.
X
D A factory method cannot be used to instantiate one of the subclasses rather than the class itself.
6. Which of the following concepts is used to provide a class access to the private components of the other class? Choose the correct answer.
420
X
A Singleton
X
B Friendship
X
C Interface
X
D Casting
© Copyright. All rights reserved.
UNIT 10
Program Calls and Memory Management
Lesson 1 Using Shared Objects Exercise 24: Use Shared Objects
422 439
UNIT OBJECTIVES ●
Explain shared objects
●
Use shared objects
© Copyright. All rights reserved.
421
Unit 10 Lesson 1 Using Shared Objects
LESSON OVERVIEW This lesson explains how you can save data as shared objects in shared memory, and examines this concept and its implementation. Business Example You want to develop a transaction in which many users can access the same data concurrently without having to read it from the database each time. You know that shared objects can be used to make data in the main memory accessible across session boundaries. Accordingly, you must familiarize yourself with this technique. For this reason, you require the following knowledge: ●
An understanding of how classes are created for shared objects
●
An understanding of how you can use shared objects to implement applications
●
An understanding of how to access shared objects from within an ABAP program
LESSON OBJECTIVES After completing this lesson, you will be able to: ●
Explain shared objects
●
Use shared objects
Motivation for Shared Objects You can save data as shared objects in shared memory, across different programs and even different user sessions. Accordingly, you can create applications which write data to this area. Other applications can then read this data later. The Potential Uses for Shared Objects ●
Saving a catalog An author writes the catalog to the shared objects area. Many users can then access this catalog at the same time.
●
Saving a shopping cart The buyer fills the shopping cart and the seller reads the filled shopping cart later.
422
© Copyright. All rights reserved.
Lesson: Using Shared Objects
Shared Memory Areas
Figure 159: Memory Model of an Application Server
Shared memory is a memory area on an application server that the ABAP programs running on the same server can access. Before SAP introduced shared objects, ABAP statements had to use the EXPORT and IMPORT statements with the SHARED BUFFER and SHARED MEMORY additions to access this memory area. Instances of classes were active exclusively in the internal session of an ABAP program. With the introduction of shared objects, shared memory has been enhanced with Shared Objects Memory, where an application can save shared objects. You can save shared objects in areas of shared memory.
Note: Instances of classes can be saved. It is not yet possible to save any data objects as shared objects. However, data objects (except for reference variables) can be saved as attributes of classes.
© Copyright. All rights reserved.
423
Unit 10: Program Calls and Memory Management
Access Shared Objects
Figure 160: Accessing Shared Objects
The figure Accessing Shared Objects explains how shared objects can be accessed from multiple user sessions simultaneously. Shared Objects ●
Should be used for cross-program buffering of data that is read often, but rarely written.
●
Concurrent read accesses are supported by shared objects.
●
Access is controlled by a lock mechanism.
●
Data is saved as attributes of objects.
●
Memory bottlenecks result in runtime errors and have to be caught.
The write accesses should not be frequent because writing data to the shared objects area is performance intensive. Specifically, you want to optimize runtime, which would not be the case if write access were more frequent.
Note: SAP also uses shared objects. For example, this technique is used to navigate in the ABAP Workbench. In addition to saving memory which is around 3 MB per user logon, navigation during the first access is faster by up to a factor of 100. A prerequisite for saving an object in shared memory is that you need to define the class with the SHARED MEMORY ENABLED addition in the CLASS statement (if the class is local), or if the class is a global class, select the SHARED MEMORY ENABLED attribute in the Class Builder.
424
© Copyright. All rights reserved.
Lesson: Using Shared Objects
Areas and Area Instances
Figure 161: Areas and Area Instances
An area is the template for area instances in shared memory. One area can generate several area instances, which differ by name. In addition, an area instance can have several versions which differ in their version IDs or version numbers. In the simplest case, without version management, an area instance consists of a single area instance version. Area Classes and Area Handles
Figure 162: Creating an Area
You define an area in transaction SHMA. This creates a global, final area class of the same name. This is a subclass of CL_SHM_AREA. In an ABAP program, you can access the area exclusively using methods of the generated area class.
© Copyright. All rights reserved.
425
Unit 10: Program Calls and Memory Management
Hint: As the area and area class have the same name, it is advised to name the area according to the naming conventions for classes - ZCL_*, for example, in the customer namespace. You can use static methods (Attach methods) of an area class to attach an ABAP program, or its internal session where the system processes the ABAP program, to an area instance in shared memory. When you attach an ABAP program, an instance of the area class is created as an area handle. The figure Creating an Area also illustrates another class, which is the area root class. You can create any number of objects in an area instance, depending on your specific program. You access these objects uniformly through the instance of the area root class.
Note: In the following example, only two classes are used.
Creation of Objects in Shared Memory
Figure 163: Example Application
A simple catalog application will be used as an example, where shared objects will be used to create a catalog of flight dates, so that users can select any flight quickly.
426
© Copyright. All rights reserved.
Lesson: Using Shared Objects
Accessing Areas
Figure 164: Accessing Areas
The figure Accessing Areas highlights the fact that any programs can access objects in shared objects memory. In this case, two applications, which run in different user sessions, access objects in the same area. For the example application, the requirements are as follows: ●
Creating an area
●
Developing a program to create an area instance
●
Developing a program to read data from the area
Shared Memory Area – Definition
Figure 165: Area Management
Shared objects are saved in areas of shared memory. You can use transaction SHMA to create and manage areas and their attributes.
© Copyright. All rights reserved.
427
Unit 10: Program Calls and Memory Management
Hint: Note that you have to call transaction code SHMA directly as it has not yet been integrated into the Object Navigator (transaction SE80). Call transaction code SHMA and enter the name of the area. The usual namespace rules apply, which means the area name has to start with Y or Z in a customer system. The system also supports namespaces containing slashes.
Hint: Note that, for this area, the system generates an identically named global and final area class as a subclass of CL_SHM_AREA. Therefore, it is advised to choose the area name wisely, as shown in the example. In an ABAP program, an area is accessed exclusively using methods of the generated area class. Maintenance of Areas
Figure 166: Maintaining Areas
After you choose one of the buttons Create, Change, or Display, the system displays the maintenance screen for areas. Each area is linked with a global area root class, whose attributes can contain proprietary data and references to other shared memory-enabled classes. You have to assign the area root class to an area when you maintain it. If an area instance version is not empty, it has to contain at least an instance of the area root class as its root object, which the system uses to reference other objects. When you generate the area class, the system generates and types a ROOT attribute with the static type of the area root class.
428
© Copyright. All rights reserved.
Lesson: Using Shared Objects
Important properties of an area are as follows: ●
Client-dependent area Areas, and thus the objects within an area, do not have a client ID by default. You can however specify an area as client-dependent. In client-dependent areas, the methods of the area class for accessing an area instance refer to the active client by default. You can use the optional importing parameter CLIENT to access another client explicitly.
●
Transactional area An area instance version of a transactional area is not active immediately after you remove a change lock with the DETACH_COMMIT method. It is not active until the next database commit. This is particularly helpful in implementing shopping carts in shared objects memory.
Shared Memory Area – Write Access
Figure 167: Before Creating an Area Instance
Once you have defined an area, and created the classes that will be instantiated, you need to understand the statements which can be used to create an area instance. The previous example will continue to be used. When you create an area, the system creates a global final class with the same name. To set up an area or access an existing area, you need a reference variable typed with reference to the generated area class. This reference serves as a handle for accessing the area.
© Copyright. All rights reserved.
429
Unit 10: Program Calls and Memory Management
Area Instance Creation
Figure 168: Area Instance Creation
When you instantiate the area class, the system creates an instance of the area in shared memory. The program has a handle for this instance of the area. It performs all future operations using this handle. Object Generation in Shared Memory
Figure 169: Object Generation in Shared Memory
Once you create the area instance, you can create the objects in the shared objects memory. To do so, use the AREA HANDLE addition for the CREATE OBJECT statement. This statement informs the system about the area instance where it should create the objects.
430
© Copyright. All rights reserved.
Lesson: Using Shared Objects
Object Generation in Shared Memory II
Figure 170: Object Generation in Shared Memory II
The figure Object Generation in Shared Memory II illustrates how you can instantiate both objects from within the program. Alternatively, you can instantiate only the root object from within the program. You can create the other objects in this area instance from the constructor of the root without assigning references. Root Object Setting
Figure 171: Root Object Setting
© Copyright. All rights reserved.
431
Unit 10: Program Calls and Memory Management
To address the objects that you create in the area instance, assign the reference to the root object to the ROOT attribute of the area handle. To do so, use the SET_ROOT method of the area handle. As a consequence, any program of any application can access this area and the objects inside it. To do so, the application merely has to fetch a reference to the area instance, and can then immediately access the objects contained in that area instance. Write Lock Releasing
Figure 172: Write Lock Releasing
Read access of an area instance is not possible until the release of the write lock. To release the lock, use the DETACH_COMMIT method, which is inherited by the area class from CL_SHM_AREA.
Shared Memory Monitor
Figure 173: Shared Memory Monitor
The Shared Memory Monitor (Transaction SHMM) provides an overview of the area instances in the shared objects memory of the current application server, and offers selected functions for it.
432
© Copyright. All rights reserved.
Lesson: Using Shared Objects
Note: Use the CL_SHM_UTILITIES class to programmatically query the attributes of area instances. The monitor provides the following four overview screens which follow on from each other: ●
Areas
●
Area instances
●
Versions
●
Locks
Double-clicking a row in the current overview takes you to the next overview, for example, from the overview of area instances to the list of versions of this area instance. From the instance overview, you can display the list of locks on a parallel tab. In the list of areas, area instances, and area instance versions, you can select a view that groups the displayed data. The following views are available: ●
Overview (displays the most important data)
●
Locks (lock statistics)
●
Users (who created/modified the area)
●
Control (memory usage and so on)
●
All columns
Read Access to Shared Memory
Figure 174: Accessing an Existing Object in Shared Memory
Once an area instance has been set up, other users and applications can access it. The reading programs have to implement the following steps:
© Copyright. All rights reserved.
433
Unit 10: Program Calls and Memory Management
1. The read program first needs a reference variable that is typed with reference to the area class. This reference variable serves as a handle for the area instance access. 2. The program obtains the handle for the area instance using method ATTACH_FOR_READ from the area class. This sets a read lock that prevents the system from deleting the area instance during the access. 3. The objects in this area instance are now accessible by using the area handle. Read Lock Cancellation
Figure 175: Read Lock Cancellation
Once the read activity is complete, the application releases the read lock using the method DETACH of the area handle. The application automatically releases the read lock when the internal session is closed after a DETACH statement.
434
© Copyright. All rights reserved.
Lesson: Using Shared Objects
Shared Memory Area Versioning
Figure 176: Setting a Read Lock on the Active Version
When you create an area, you can specify that the system allows several versions of an area instance. The figure Setting a Read Lock on the Active Version shows an area instance that has been set up. Once the setup is complete using method DETACH_COMMIT, and the system sends a database commit, the area instance version is active. Version Being Set Up
Figure 177: Version Being Set Up
© Copyright. All rights reserved.
435
Unit 10: Program Calls and Memory Management
If the NUMBER OF VERSIONS attribute of the area is set appropriately, additional versions of the area instance can exist in addition to the active version. When a new catalog is being set up, several temporary versions of the same area instance exist concurrently. As soon as an application sets a change lock for an area instance, a “version being set up” is created and exists in parallel to the active version. Write Complete – Previous Version is Outdated
Figure 178: Write Complete – Previous Version is Outdated
If you complete the setup of the new version during a read access of the currently active version, the version being set up becomes active. The previously active version is given the attribute OUTDATED.
436
© Copyright. All rights reserved.
Lesson: Using Shared Objects
New Read Locks for the New Active Version
Figure 179: New Read Locks for the New Active Version
The read locks for the outdated version remain until the read operations are complete. In contrast, new read locks for the area instance are always set for the active version. Therefore, two different readers can produce two different read results in this case. No More Read Locks for Outdated Version – Version Expired
Figure 180: No More Read Locks for Outdated Version – Version Expired
When you remove the last existing read lock from an outdated version, the outdated version expires. The garbage collector then deletes the expired version. You cannot set any locks for
© Copyright. All rights reserved.
437
Unit 10: Program Calls and Memory Management
expired versions, nor are they used to determine the number of versions (the latter is important if the number of area instance versions has been restricted). New Read Locks for Active Version
Figure 181: New Read Locks for Active Version
New read locks are always set for the active version. There can only be one active version for each area instance. Depending on the maximum number of versions, several outdated versions for which read locks are still set can exist in parallel to the new version.
438
© Copyright. All rights reserved.
Unit 10 Exercise 24 Use Shared Objects
Business Example You want to run an Internet shop based on an SAP system. To give your Internet customers the fastest possible access to your catalog, you save it in shared objects memory. Write a program to manage and fill the catalog and develop a test application to read the data. Template None Solution CL_BC402_SHS_ROOT (global class) CL_BC402_SHS_CATALOG (global class) BC402_SHS_WRITE_CATALOG (executable program) BC402_SHS_READ_CATALOG (executable program)
Note: In the exercises for this course, when the input values include ##, replace ## with your group number. Create a Global Catalog Class Create a global class where the catalog data is to be saved (suggested name: ZCL_BC402_##_CATALOG). This class requires a method for writing the catalog data and another method for retrieving the data. It also requires a global attribute (an internal table) to store the catalog data. 1. Create the global class for the catalog data. Note that this class has to be shared memoryenabled. 2. Create a private instance attribute in the class (suggested name: GT_CATALOG). For its type, use a suitable table type that has structure SDYN_CONN as a line type. 3. Create a public instance method to fill the catalog (suggested name: FILL_CATALOG). This method requires an importing parameter that will be passed the internal table with data. Implement the method. Use the details in the following table: Parameter
Type
Associated Type
IT_CATALOG
Importing
BC402_T_SDYNCONN
4. Create a second public instance method that can be used for flight date queries (suggested name: GET_FLIGHTS). This method requires one importing parameter each for the departure and destination cities, as well as two additional parameters for the
© Copyright. All rights reserved.
439
Unit 10: Program Calls and Memory Management
different flight dates. The method also needs an exporting parameter that returns the matching flights. Implement the method. Use the details in the following table: Parameter
Type
Associated Type
IV_FROM_CITY
Importing
S_FROM_CIT
IV_TO_CITY
Importing
S_TO_CITY
IV_EARLIEST
Importing
S_DATE
IV_LATEST
Importing
S_DATE
ET_FLIGHTS
Exporting
BC402_T_SDYNCONN
Create an Area in Shared Objects Memory Create an area in shared objects memory (suggested name: ZCL_BC402_##_AREA). 1. Create the area root class. It should merely contain a reference to the catalog class that you created in the first task. Look at model solution class CL_BC402_SHS_ROOT. Define a public instance attribute using the information in the following table: Attribute
Type
Associated Type
MO_CATALOG
TYPE REF TO
ZCL_BC402_##_CATALOG
2. Use transaction SHMA to create an area in shared memory. This area should have the following attributes: ●
Client-Specific Area
●
With Versioning
●
Displacement Not Possible
You must specify a root class. Enter ZCL_BC402_##_ROOT, which you created in the previous step. Create an Executable Program to Write to Shared Memory Create an executable program that builds the area in shared objects memory (suggested name: ZBC402_##_WRITE_CATALOG). This program is also supposed to read the catalog data from the database and pass it on to the appropriate class. 1. In SE80, create an executable program. 2. Define three reference variables, one each for the area handle, the area root class, and the catalog class. 3. Create an area, an instance of the catalog class, and an instance of the area root class. Set up the area. Read the necessary catalog data from tables SPFLI and SFLIGHT. 4. Ensure to delete the write lock after the data is written successfully. 5. Execute the program and use the Shared Objects Monitor to examine the shared memory area.
440
© Copyright. All rights reserved.
Lesson: Using Shared Objects
Create an Executable Program to Read from Shared Memory Implement a read program to read data from the area you just created (suggested name: ZBC402_##_READ_CATALOG). Output the data in a simple user dialog (using the provided function module BC402_DISPLAY_TABLE). 1. Create an executable program. 2. Define a selection screen in which the user can enter the departure and destination cities. The user should also be able to enter an earliest and latest possible flight date. 3. Make sure the data is read from the catalog object. Output the data in the user dialog.
© Copyright. All rights reserved.
441
Unit 10 Solution 24 Use Shared Objects
Business Example You want to run an Internet shop based on an SAP system. To give your Internet customers the fastest possible access to your catalog, you save it in shared objects memory. Write a program to manage and fill the catalog and develop a test application to read the data. Template None Solution CL_BC402_SHS_ROOT (global class) CL_BC402_SHS_CATALOG (global class) BC402_SHS_WRITE_CATALOG (executable program) BC402_SHS_READ_CATALOG (executable program)
Note: In the exercises for this course, when the input values include ##, replace ## with your group number. Create a Global Catalog Class Create a global class where the catalog data is to be saved (suggested name: ZCL_BC402_##_CATALOG). This class requires a method for writing the catalog data and another method for retrieving the data. It also requires a global attribute (an internal table) to store the catalog data. 1. Create the global class for the catalog data. Note that this class has to be shared memoryenabled. a) In SE80, in the unnamed dropdown list on the left of the screen, choose Class/ Interface and specify the name of the class ZCL_BC402_##_CATALOG. b) Choose Display. A Create Class/Interface dialog box appears. c) To create the class, choose Yes. A Create Class ZCL_BC402_##_CATALOG dialog box appears. d) In the Create Class ZCL_BC402_##_CATALOG dialog box, enter a description and choose Save. e) In the Create Object Directory Entry dialog box, in the Package field, enter ZBC402_## and choose Save.
442
© Copyright. All rights reserved.
Lesson: Using Shared Objects
f) In the Prompt for transportable Workbench request dialog box, choose Continue. g) In the Object list, double-click the program name. 2. Create a private instance attribute in the class (suggested name: GT_CATALOG). For its type, use a suitable table type that has structure SDYN_CONN as a line type. a) With ZCL_BC402_##_CATALOG open in the Class Builder, in the Attributes tab, choose the Display <-> Change button. b) Create the attribute GT_CATALOG as a private, instance attribute, with BC402_T_SDYNCONN in the Associated Type column and choose Save. 3. Create a public instance method to fill the catalog (suggested name: FILL_CATALOG). This method requires an importing parameter that will be passed the internal table with data. Implement the method. Use the details in the following table: Parameter
Type
Associated Type
IT_CATALOG
Importing
BC402_T_SDYNCONN
a) With ZCL_BC402_##_CATALOG open in the Class Builder, choose the Methods tab. b) In the Method column, enter FILL_CATALOG and set the method as a public, instance method. c) Place your cursor in the FILL_CATALOG cell and choose the Parameters button. d) Enter the details in the table above and, on your keyboard, press the Enter key. e) Choose the Code button and write the code. f) See the source code excerpt from the model solution. g) Choose the Check button. h) Choose the Activate button. 4. Create a second public instance method that can be used for flight date queries (suggested name: GET_FLIGHTS). This method requires one importing parameter each for the departure and destination cities, as well as two additional parameters for the different flight dates. The method also needs an exporting parameter that returns the matching flights. Implement the method. Use the details in the following table: Parameter
Type
Associated Type
IV_FROM_CITY
Importing
S_FROM_CIT
IV_TO_CITY
Importing
S_TO_CITY
IV_EARLIEST
Importing
S_DATE
IV_LATEST
Importing
S_DATE
ET_FLIGHTS
Exporting
BC402_T_SDYNCONN
a) With ZCL_BC402_##_CATALOG open in the Class Builder, choose the Methods tab. b) In the Method column, enter GET_FLIGHTS and set the method as a public, instance method.
© Copyright. All rights reserved.
443
Unit 10: Program Calls and Memory Management
c) Place your cursor in the GET_FLIGHTS cell and choose the Parameters button. d) Enter the details in the table above and, on your keyboard, press the Enter key. e) Choose the Code button and write the code. f) See the source code excerpt from the model solution. g) Choose the Check button. h) Choose the Activate button. Create an Area in Shared Objects Memory Create an area in shared objects memory (suggested name: ZCL_BC402_##_AREA). 1. Create the area root class. It should merely contain a reference to the catalog class that you created in the first task. Look at model solution class CL_BC402_SHS_ROOT. Define a public instance attribute using the information in the following table: Attribute
Type
Associated Type
MO_CATALOG
TYPE REF TO
ZCL_BC402_##_CATALOG
a) In the Class builder create the class ZCL_BC402_##_ROOT, choose the Properties tab, and select the Shared-Memory Enabled checkbox. b) Choose the Attributes tab and enter the information in the table above. c) Save and activate the class. 2. Use transaction SHMA to create an area in shared memory. This area should have the following attributes: ●
Client-Specific Area
●
With Versioning
●
Displacement Not Possible
You must specify a root class. Enter ZCL_BC402_##_ROOT, which you created in the previous step. a) In the Command field, enter transaction code SHMA. b) In the Shared Objects: Area Management screen, in the Area Name field, enter ZCL_BC402_##_AREA and choose Create. c) In the Create Area ZCL_BC402_##_AREA screen, ensure that the Client-Specific Area and With Versioning checkboxes are selected. d) In the Displacement Type field, ensure that Displacement Not Possible is selected. e) In the Description field, enter a description and, in the Root Class field, enter ZCL_BC402_##_ROOT. Choose Save. f) In the Create Object Directory Entry dialog box, in the Package field, enter ZBC402_## and choose Save. g) In the Prompt for transportable Workbench request dialog box, choose Continue.
444
© Copyright. All rights reserved.
Lesson: Using Shared Objects
Create an Executable Program to Write to Shared Memory Create an executable program that builds the area in shared objects memory (suggested name: ZBC402_##_WRITE_CATALOG). This program is also supposed to read the catalog data from the database and pass it on to the appropriate class. 1. In SE80, create an executable program. a) In the unnamed dropdown list on the left of the screen, choose Program and specify the name of the program ZBC402_##_WRITE_CATALOG. b) Choose Display. A Create Program dialog box appears. c) To create the program, choose Yes. A Create Program dialog box appears. d) In the Create Program dialog box, choose Continue. e) In the ABAP: Program Attributes ZBC402_##_WRITE_CATALOG Change dialog box, choose Save. f) In the Create Object Directory Entry dialog box, in the Package field, enter ZBC402_## and choose Save. g) In the Prompt for transportable Workbench request dialog box, choose Continue. h) In the Object list, double-click the program name. 2. Define three reference variables, one each for the area handle, the area root class, and the catalog class. a) See the source code excerpt from the model solution. 3. Create an area, an instance of the catalog class, and an instance of the area root class. Set up the area. Read the necessary catalog data from tables SPFLI and SFLIGHT. a) See the source code excerpt from the model solution. 4. Ensure to delete the write lock after the data is written successfully. a) See the source code excerpt from the model solution. 5. Execute the program and use the Shared Objects Monitor to examine the shared memory area. a) Execute the program. b) To examine the details of the shared memory area instance, enter transaction code SHMM. Create an Executable Program to Read from Shared Memory Implement a read program to read data from the area you just created (suggested name: ZBC402_##_READ_CATALOG). Output the data in a simple user dialog (using the provided function module BC402_DISPLAY_TABLE). 1. Create an executable program. a) Return to SE80.
© Copyright. All rights reserved.
445
Unit 10: Program Calls and Memory Management
b) In the unnamed dropdown list on the left of the screen, choose Program and specify the name of the program ZBC402_##_READ_CATALOG. c) Choose Display. A Create Program dialog box appears. d) To create the program, choose Yes. A Create Program dialog box appears. e) In the Create Program dialog box, choose Continue. f) In the ABAP: Program Attributes ZBC402_##_READ_CATALOG Change dialog box, choose Save. g) In the Create Object Directory Entry dialog box, in the Package field, enter ZBC402_## and choose Save. h) In the Prompt for transportable Workbench request dialog box, choose Continue. i) In the Object list, double-click the program name. 2. Define a selection screen in which the user can enter the departure and destination cities. The user should also be able to enter an earliest and latest possible flight date. a) See the source code excerpt from the model solution. 3. Make sure the data is read from the catalog object. Output the data in the user dialog. a) See the source code excerpt from the model solution. Class CL_BC402_SHS_CATALOG: Implementation
METHOD FILL_CATALOG. gt_catalog = it_catalog. ENDMETHOD. METHOD GET_FLIGHTS. DATA gs_catalog LIKE LINE OF gt_catalog. LOOP AT gt_catalog INTO gs_catalog WHERE cityfrom = cityto = fldate > fldate <
iv_from_city AND iv_to_city AND iv_earliest AND iv_latest.
APPEND gs_catalog TO et_flights. ENDLOOP. * Alternative option using field symbols in the loop * * * * * * * *
446
FIELD-SYMBOLS: TYPE sdyn_conn. LOOP AT gt_catalog ASSIGNING WHERE cityfrom cityto fldate fldate
= = > <
iv_from_city AND iv_to_city AND iv_earliest AND iv_latest.
© Copyright. All rights reserved.
Lesson: Using Shared Objects
* * * *
APPEND TO et_flights. ENDLOOP.
ENDMETHOD.
Program BC402_SHS_WRITE_CATALOG
REPORT
bc402_shs_write_catalog.
DATA: go_handle TYPE REF TO cl_bc402_shs_area, go_root TYPE REF TO cl_bc402_shs_root, go_catalog TYPE REF TO cl_bc402_shs_catalog, gt_flights TYPE
bc402_t_sdynconn.
START-OF-SELECTION. go_handle = cl_bc402_shs_area=>attach_for_write( ). CREATE OBJECT go_root AREA HANDLE go_handle. CREATE OBJECT go_catalog AREA HANDLE go_handle. go_root->mo_catalog = go_catalog. go_handle->set_root( root = go_root ). SELECT * FROM spfli JOIN sflight ON spfli~carrid = sflight~carrid AND spfli~connid = sflight~connid INTO CORRESPONDING FIELDS OF TABLE gt_flights. go_handle->root->mo_catalog->fill_catalog( it_catalog = gt_flights ). go_handle->detach_commit( ).
Program BC402_SHS_READ_CATALOG
REPORT
bc402_shs_read_catalog.
DATA: go_handle gt_flights gs_flight
TYPE REF TO TYPE LIKE LINE OF
cl_bc402_shs_area, bc402_t_sdynconn, gt_flights,
gv_startdate TYPE sydatum,
© Copyright. All rights reserved.
447
Unit 10: Program Calls and Memory Management
gv_enddate PARAMETERS: pa_from pa_to SELECT-OPTIONS: so_date
TYPE sydatum. TYPE spfli-cityfrom, TYPE spfli-cityto. FOR sy-datum NO-EXTENSION.
AT SELECTION-SCREEN. READ TABLE so_date INDEX 1. IF so_date IS INITIAL. so_date-low = sy-datum. so_date-high = sy-datum + 365. ENDIF. gv_startdate = sy-datum. gv_enddate = sy-datum + 365. IF so_date-low > sy-datum. gv_startdate = sy-datum. ENDIF. IF so_date-high < gv_enddate. gv_enddate = so_date-high. ENDIF. START-OF-SELECTION. go_handle = cl_bc402_shs_area=>attach_for_read( ). go_handle->root->mo_catalog->get_flights( EXPORTING iv_from_city = pa_from iv_to_city = pa_to iv_earliest = gv_startdate iv_latest = gv_enddate IMPORTING et_flights = gt_flights ). go_handle->detach( ). CALL FUNCTION 'BC402_DISPLAY_TABLE' CHANGING ct_table = gt_flights.
448
© Copyright. All rights reserved.
Lesson: Using Shared Objects
LESSON SUMMARY You should now be able to: ●
Explain shared objects
●
Use shared objects
© Copyright. All rights reserved.
449
Unit 10: Program Calls and Memory Management
450
© Copyright. All rights reserved.
Unit 10 Learning Assessment
1. Shared memory is a memory area on an application server that the ABAP programs running on that server can access. Determine whether this statement is true or false. X
True
X
False
2. When working with shared objects, method __________ of the area handle is available for the application to release the read lock. Choose the correct answer. X
A DETACH_COMMIT
X
B OUTDATED
X
C DETACH
© Copyright. All rights reserved.
451
Unit 10 Learning Assessment - Answers
1. Shared memory is a memory area on an application server that the ABAP programs running on that server can access. Determine whether this statement is true or false. X
True
X
False
2. When working with shared objects, method __________ of the area handle is available for the application to release the read lock. Choose the correct answer.
452
X
A DETACH_COMMIT
X
B OUTDATED
X
C DETACH
© Copyright. All rights reserved.
UNIT 11
Dynamic Programming
Lesson 1 Using Generic Data Types Exercise 25: Use Dynamically Typed Field Symbols in Dynamic SQL Statements Exercise 26: Access Structure Components Dynamically
454 461 471
Lesson 2 Describing Data Types, Data Objects, and Objects at Runtime Exercise 27: Provide Column Headers Using RTTI
481 493
Lesson 3 Creating Data Types, Data Objects, and Objects at Runtime Exercise 28: Create Data Objects at Runtime Exercise 29: Create Data Types at Runtime with RTTC
505 511 521
UNIT OBJECTIVES ●
Explain generic data types of ABAP
●
Use generic data types
●
Access data objects dynamically
●
Use generically typed data references
●
Explain Runtime Type Identification (RTTI)
●
Describe data types and data objects at runtime
●
Describe object types and objects at runtime
●
Create objects at runtime
●
Create data objects at runtime
●
Create data types at runtime
© Copyright. All rights reserved.
453
Unit 11 Lesson 1 Using Generic Data Types
LESSON OVERVIEW This lesson discusses how to use generic data types in ABAP for dynamic programming. It also discusses the constraints posed on generic data references by the ABAP syntax and how these constraints affect generic data use. Business Example You need to develop a flexible application. Therefore, you want to find out about the generic data types in ABAP and learn how to type parameters, field symbols, and data references generically. For this reason, you require the following knowledge: ●
●
●
●
An understanding of generic types and their uses An understanding of how to use generically typed parameters, field symbols, and data references An understanding of how to use field symbols to access data objects dynamically An understanding of how to use field symbols to access attributes and structure components dynamically
LESSON OBJECTIVES After completing this lesson, you will be able to:
454
●
Explain generic data types of ABAP
●
Use generic data types
●
Access data objects dynamically
●
Use generically typed data references
© Copyright. All rights reserved.
Lesson: Using Generic Data Types
ABAP Built-In Generic Data Types
Figure 182: Generic ABAP Data Types
The figure Generic ABAP Data Types illustrates the predefined generic data types supported by ABAP syntax. In addition to complete data types, ABAP also features a number of generic data types. In contrast to complete types, you cannot use generic types to define the properties of data objects. You only use generic types to type formal parameters and field symbols. Note: Currently, the two built-in types, ... TYPE REF TO OBJECT and ... TYPE REF TO DATA are the only types available for typing reference variables generically. Generic ABAP Data Types – Internal Tables Hint: Most generic types, such as clike, csequence, numeric, simple, and xsequence, are available as of SAP Web AS 6.10. Generic type decfloat is available as of SAP NetWeaver 7.0 EhP 2.
© Copyright. All rights reserved.
455
Unit 11: Dynamic Programming
Figure 183: Generic ABAP Data Types – Internal Tables
Each of the generic types is compatible with the set of ABAP types shown in the previous figures. When you call a procedure, the system checks whether the type of the actual parameter is compatible with the type of the formal parameter. When you assign a generically typed field symbol, the syntax check tests whether the type of the data object is compatible with the generic type of the field symbol.
Note: The DATA type behaves in the same way as ANY. The differentiation is purely theoretical at this point. In the future, however, reference variables with type TYPE REF TO ANY to point to data objects or instances of classes might be possible. The ANY TABLE, INDEX TABLE, and SORTED TABLE are special generic data types that are only compatible with internal tables.
Freely Defined Generic Table Types
Figure 184: Generic Table Types – User-Defined
In addition to these built-in generic table types, ABAP also contains generic table types that developers create as generic types. These generic table types are created either in the ABAP Dictionary or in the program source code, with the TYPES statement. The figure Generic Table Types — User-Defined shows an example of locally defined generic table types.
456
© Copyright. All rights reserved.
Lesson: Using Generic Data Types
In these generic table types, you define the line type, but the table type and key definition remain open.
Note: To create appropriate generic types in the ABAP Dictionary, check the corresponding options under the Access and Key tabs.
Generically Typed Parameters
Figure 185: Problems When Parameters Are Too General
When you generically type formal parameters of a procedure, such as a subroutine, function module, or method, the procedure becomes more flexible. Use the syntax check to ensure that the procedure handles the different types. The syntax check ensures that the system passes only actual parameters with compatible types to generically typed formal parameters. However, when generically typed parameters are addressed in ABAP statements, you often cannot determine whether the type of the underlying data object or its current content is logical in the respective operand position until runtime. If conflicts occur, the system raises runtime errors that cannot be caught in most cases. The figure Problems When Parameters Are Too General shows an example. If you assign an internal table or a structure that is not flat and character-type to the parameter in the example, the WRITE statement raises an uncatchable exception, OBJECTS_NOT_CHARCONV. The syntax check helps avoid such runtime errors, particularly in operand positions that only allow internal tables, such as SELECT ... INTO TABLE ... and LOOP AT TABLE .... Only generic table types are accepted in these operand positions. Therefore, ensure that an internal table comes after the formal parameter. To avoid syntax errors and runtime errors, select generic types that are specific enough to be used with all compatible types in the desired operand position.
© Copyright. All rights reserved.
457
Unit 11: Dynamic Programming
Type Precisely to Avoid Errors
Figure 186: Avoiding Errors by Typing as Precisely as Possible
If you use the generic type SIMPLE in the example shown in the figure Avoiding Errors by Typing as Precisely as Possible, the WRITE statement does not cause runtime errors. You can convert all data types that are compatible with SIMPLE to a character string. The syntax errors are corrected because parameter it_data now accepts only internal tables because of its type, ANY TABLE.
Hint: A runtime error can still occur if the method contains an index access to it_data, specifically, if the actual parameter is a hashed table. Use the generic type INDEX TABLE to restrict the formal parameter even further.
458
© Copyright. All rights reserved.
Lesson: Using Generic Data Types
Generically Typed Field Symbols
Figure 187: Example – Generic Field Symbol in Dynamic SELECT
Field symbols are pointers that can be assigned to data objects dynamically. When the field symbol is used in an ABAP statement, you can dynamically define the specific data object that the field symbol refers to. If the field symbol is fully typed, then all potential data objects must have the same type, which restricts the possible use of the field symbol significantly. Generic typing enables the field symbol to refer to data objects with different types. As a result, you can address different data objects in the same operand position of an ABAP statement. The figure Example — Generic Field Symbol in Dynamic SELECT shows an example of how to use a field symbol in a dynamic SELECT statement. The program needs to access one of two database tables, SCARR or SBOOK, depending on the content of data object gv_table_name. To achieve this, a dynamic SELECT statement is used. To ensure that the line type of the internal table matches the field list of the database table, a generically typed field symbol is used as a target that points to internal table gt_scarr or gt_sbook, as required.
Hint: The field symbol cannot have type ANY. If the field symbol assigned to the internal tables has type ANY, it causes a syntax error when used in the SELECT statement.
Note: This example is not completely dynamic, because the data objects are still defined statically.
© Copyright. All rights reserved.
459
Unit 11: Dynamic Programming
Type Casting With Field Symbols
Figure 188: Type Casting With Field Symbols
If the CASTING addition is used when a data object is assigned to a field symbol that has a different type, the restrictions of having to use the data objects original type are removed. If the CASTING TYPE addition is used when assigning a data object to a field symbol that has a different type, the data object can be accessed using the field symbol as if it has that explicitly specified type. In the figure Type Casting for Field Symbols, note that the system field SY-DATUM is an elementary character-type component of length 8.
460
© Copyright. All rights reserved.
Unit 11 Exercise 25 Use Dynamically Typed Field Symbols in Dynamic SQL Statements
Business Example You need to develop a simple program that displays the contents of any database table. Define the database table in a SELECT statement dynamically, and use a generically typed field symbol to specify the target of the SELECT statement dynamically.
Note: In the next step, replace two static SELECT statements with a dynamic statement.
Note: In the exercises for this course, when the input values include ##, replace ## with your group number. Copy the Template Program Copy program BC402_DYS_DYN_CALL or your own program ZBC402_##_DYN_CALL and name it ZBC402_##_DYN_SQL, where ## is your group number. Familiarize yourself with the program and how it works. 1. Copy the program and all its subcomponents. 2. Activate and test the program. 3. Analyze the source code. How is the data read from the database and into which data objects is it transferred?
Program a Dynamic SQL Statement Replace the two SELECT statements with a single SELECT statement after the ENDCASE statement. Specify the table name as a character-type data object. In addition, use a generically typed field symbol as the target (INTO clause) to which you dynamically assign a suitable data object. 1. Define a character-type data object for the table name (suggested name is gv_tabname). Fill the data object with the respective table names in the WHEN blocks.
© Copyright. All rights reserved.
461
Unit 11: Dynamic Programming
2. Create a field symbol (suggested name is ) whose type allows either data object gt_conn or gt_cust to be assigned to it. 3. Why is type ANY not suitable?
4. Assign the field symbol to the respective internal tables in the WHEN blocks, the ones you want to fill in the generic SELECT statement. 5. Move one of the two SELECT statements from the WHEN block to after the ENDCASE statement and delete the other one. Make the remaining database access dynamic. Replace the static table name with data object gv_tabname and replace the target (internal table) with the field symbol. Catch Dynamic SQL Statement Runtime Errors 1. Read the keyword documentation to find out about the exceptions that occur when using dynamic SQL statements. Implement exception handling with TRY... CATCH ... ENDTRY. Either implement a separate CATCH block for each of the exception classes or use a single CATCH block for the shared superclass. If an error occurs, respond with error message 061 from message class BC402. 2. Activate and test the program.
462
© Copyright. All rights reserved.
Unit 11 Solution 25 Use Dynamically Typed Field Symbols in Dynamic SQL Statements
Business Example You need to develop a simple program that displays the contents of any database table. Define the database table in a SELECT statement dynamically, and use a generically typed field symbol to specify the target of the SELECT statement dynamically.
Note: In the next step, replace two static SELECT statements with a dynamic statement.
Note: In the exercises for this course, when the input values include ##, replace ## with your group number. Copy the Template Program Copy program BC402_DYS_DYN_CALL or your own program ZBC402_##_DYN_CALL and name it ZBC402_##_DYN_SQL, where ## is your group number. Familiarize yourself with the program and how it works. 1. Copy the program and all its subcomponents. a) To start the Object Navigator, enter transaction code se80. b) In the unnamed dropdown menu on the left of the screen, choose Program and specify the name of the program ZBC402_##_DYN_CALL. c) Choose Display. d) Right-click ZBC402_##_DYN_CALL and choose Copy.... e) In the Copy Program ZBC402_##_DYN_CALL dialog box, in the Target program field, enter ZBC402_##_DYN_SQL and choose Copy. f) In the Copy Program ZBC402_##__DYN_CALL to ZBC402_##_DYN_SQL dialog box, select all checkboxes and choose Copy. g) In the Create Object Directory Entry dialog box, in the Package field, enter ZBC402_## and choose Save. 2. Activate and test the program. a) Choose the Check button.
© Copyright. All rights reserved.
463
Unit 11: Dynamic Programming
b) Choose the Activate button. c) Choose the Direct Processing button. 3. Analyze the source code. How is the data read from the database and into which data objects is it transferred? The data is read from the database in static SELECT statements. In the process, one of two statically defined internal tables is filled. Program a Dynamic SQL Statement Replace the two SELECT statements with a single SELECT statement after the ENDCASE statement. Specify the table name as a character-type data object. In addition, use a generically typed field symbol as the target (INTO clause) to which you dynamically assign a suitable data object. 1. Define a character-type data object for the table name (suggested name is gv_tabname). Fill the data object with the respective table names in the WHEN blocks. a) See the source code excerpt from the model solution. 2. Create a field symbol (suggested name is ) whose type allows either data object gt_conn or gt_cust to be assigned to it. a) See the source code excerpt from the model solution. 3. Why is type ANY not suitable? The field symbol should be specified after INTO TABLE in the SELECT statement. The syntax check only allows generic values here, with at least type ANY TABLE. 4. Assign the field symbol to the respective internal tables in the WHEN blocks, the ones you want to fill in the generic SELECT statement. a) See the source code excerpt from the model solution. 5. Move one of the two SELECT statements from the WHEN block to after the ENDCASE statement and delete the other one. Make the remaining database access dynamic. Replace the static table name with data object gv_tabname and replace the target (internal table) with the field symbol. a) See the source code excerpt from the model solution. Catch Dynamic SQL Statement Runtime Errors 1. Read the keyword documentation to find out about the exceptions that occur when using dynamic SQL statements. Implement exception handling with TRY... CATCH ... ENDTRY. Either implement a separate CATCH block for each of the exception classes or use a single CATCH block for the shared superclass. If an error occurs, respond with error message 061 from message class BC402. a) See the source code excerpt from the model solution. 2. Activate and test the program. a) Choose the Check button. b) Choose the Activate button.
464
© Copyright. All rights reserved.
Lesson: Using Generic Data Types
c) Choose the Direct Processing button. Source code excerpt from the model solution: REPORT
bc402_dys_dyn_sql MESSAGE-ID bc402.
TYPE-POOLS: abap. DATA: gt_cust gt_conn
TYPE ty_customers, TYPE ty_connections.
DATA: gv_methname TYPE string, gt_parmbind TYPE abap_parmbind_tab, gs_parmbind TYPE abap_parmbind. DATA: gv_tabname
TYPE string.
FIELD-SYMBOLS: TYPE ANY TABLE. SELECTION-SCREEN COMMENT 1(80) text-sel. PARAMETERS: pa_xconn TYPE xfeld RADIOBUTTON GROUP tab DEFAULT 'X', pa_xcust TYPE xfeld RADIOBUTTON GROUP tab . PARAMETERS: pa_nol TYPE i DEFAULT '100'. START-OF-SELECTION. * specific part *------------------------------------------* CASE 'X'. WHEN pa_xconn. gv_tabname = 'SPFLI'. ASSIGN gt_conn TO . gv_methname = 'WRITE_CONNECTIONS'. gs_parmbind-name = 'IT_CONN'. GET REFERENCE OF gt_conn INTO gs_parmbind-value. INSERT gs_parmbind INTO TABLE gt_parmbind. WHEN pa_xcust. gv_tabname = 'SCUSTOM'. ASSIGN gt_cust TO . gv_methname = 'WRITE_CUSTOMERS'. gs_parmbind-name = 'IT_CUST'. GET REFERENCE OF gt_cust INTO gs_parmbind-value. INSERT gs_parmbind INTO TABLE gt_parmbind. ENDCASE.
© Copyright. All rights reserved.
465
Unit 11: Dynamic Programming
* dynamic part *---------------------------------------------* TRY.
SELECT * FROM (gv_tabname) INTO TABLE UP TO pa_nol ROWS. CATCH cx_sy_dynamic_osql_error. MESSAGE e061. ENDTRY. TRY.
CALL METHOD cl_bc402_utilities=>(gv_methname) PARAMETER-TABLE gt_parmbind.
CATCH cx_sy_dyn_call_error. MESSAGE e060. ENDTRY.
466
© Copyright. All rights reserved.
Lesson: Using Generic Data Types
Dynamic Access to Data Objects
Figure 189: Dynamic Access to Data Objects
In most ABAP statements, you cannot replace data objects in operand positions directly with character-type data objects in parentheses. However, this option is available in the ASSIGN statement for the data object to which you assign the field symbol. This approach indirectly makes it possible to call the data object dynamically by its name. You have to assign a generically typed field symbol to the data object using the syntax in the figure Dynamic Access to Data Objects. Then use that field symbol in the ABAP statement. There are easier and less error-prone alternatives to specifically access attributes and structure components.
Dynamic Access to Instance Attributes and Class Attributes
Figure 190: Dynamic Access to Object Attributes and Class Attributes
© Copyright. All rights reserved.
467
Unit 11: Dynamic Programming
In addition to using the full identifier for dynamic access to attributes of classes and objects, you can also specify only the attribute name with a character-type data object. The object reference and component selector are specified statically. You can also dynamically specify the class name for static attributes, if necessary. This syntax is similar to that used for dynamic method calls.
Hint: Because the syntax check supports the static part of the statement, these variants are less error-prone and are therefore preferred.
Dynamic Access to Structure Components
Figure 191: Dynamic Access to Structure Components
A special variant of the ASSIGN statement provides access to structure components dynamically. You specify the structure statically or through a separate field symbol in the ASSIGN COMPONENT ... OF STRUCTURE ... statement. Address the components either by name or by position (number) within the structure.
Hint: Because the syntax check supports the static part of the statement, these variants are less error-prone and are therefore preferred. Because the system addresses the components of a structure by their positions in sequence, you can process any structure completely, component by component.
468
© Copyright. All rights reserved.
Lesson: Using Generic Data Types
Full Processing of Any Non-Nested, Flat Structure
Figure 192: Full Processing of Any Non-Nested Flat Structure
Caution: In the figure Full Processing of Any Non-Nested Flat Structure, an uncatchable ASSIGN_TYPE_CONFLICT runtime error occurs if the transferred structure contains a component that is incompatible with the generic SIMPLE type of the field symbol. Similarly, a runtime error occurs during the WRITE statement if you type the field symbol with ANY.
© Copyright. All rights reserved.
469
Unit 11: Dynamic Programming
470
© Copyright. All rights reserved.
Unit 11 Exercise 26 Access Structure Components Dynamically
Business Example You need to develop a simple program that displays the contents of any database table. You therefore want to find out about the options available in dynamic programming. To implement a generic method that enables you to output the contents of any table in a list (provided the line type of the internal table has a flat structure), replace the dynamic call of two specific methods with a static call of a generic method.
Note: In the exercises for this course, when the input values include ##, replace ## with your group number. Copy Global Class CL_BC402_DYT_GEN_TYPES Copy global class CL_BC402_DYT_GEN_TYPES and name it ZCL_BC402_##_GEN_TYPES. Familiarize yourself with the class definition. 1. Copy the global class. 2. Analyze the class definition. Which methods are defined? What is their purpose?
3. Which parameters do these methods have? How are the parameters typed?
Implement Method write_any_struct Implement method write_any_struct, and output all components of structure gs_struct individually with a WRITE statement by programming a loop in which you access all the components in structure gs_struct consecutively. 1. Create a field symbol (suggested name is ) that has a generic type that allows assignment of any flat components of the structure. 2. Program a DO loop. Use the sy-index loop counter to access all components of gs_struct consecutively with the field symbol. 3. Check whether the field symbol assignment was successful. If it was, output the component with a WRITE statement. Otherwise, exit the loop.
© Copyright. All rights reserved.
471
Unit 11: Dynamic Programming
Implement Method write_any_table Implement method write_any_table. Display the contents of internal table it_table in a list by programming a loop. Call your previously implemented method, write_any_struct, for each line. 1. Create a field symbol (suggested name is ) that has a generic type that allows assignment of a line of generic internal table it_table. 2. Program a LOOP over internal table it_table. Assign the lines in the internal table to field symbol consecutively. 3. Call method write_any_struct for each line. Copy the Template Program Copy program BC402_DYS_DYN_SQL or your own program ZBC402_##_DYN_SQL and name it ZBC402_##_GEN_TYPES, where ## is your group number. Familiarize yourself with the program and how it works. 1. Copy the program and all its subcomponents. 2. Activate and test the program. Analyze the source code. Replace a Dynamic Method Call with a Generic Method Replace the dynamic method call at the end of the program with a call of your new method, write_any_table. Remove all parts of the source code you no longer need, or comment them out. 1. Delete the dynamic method call or comment it out. In its place, implement a call of method write_any_table. Pass the method the generic field symbol that points to the internal table with the data. 2. Delete the definitions of the data objects that are needed for the dynamic method call or comment them out. 3. Activate and test the program.
472
© Copyright. All rights reserved.
Unit 11 Solution 26 Access Structure Components Dynamically
Business Example You need to develop a simple program that displays the contents of any database table. You therefore want to find out about the options available in dynamic programming. To implement a generic method that enables you to output the contents of any table in a list (provided the line type of the internal table has a flat structure), replace the dynamic call of two specific methods with a static call of a generic method.
Note: In the exercises for this course, when the input values include ##, replace ## with your group number. Copy Global Class CL_BC402_DYT_GEN_TYPES Copy global class CL_BC402_DYT_GEN_TYPES and name it ZCL_BC402_##_GEN_TYPES. Familiarize yourself with the class definition. 1. Copy the global class. a) To start the Object Navigator, enter transaction code se80. b) In the unnamed dropdown menu on the left of the screen, choose Class/Interface and specify the name of the class CL_BC402_DYT_GEN_TYPES. c) Choose Display. d) Right-click CL_BC402_DYT_GEN_TYPES and choose Copy.... e) In the Copy CL_BC402_DYT_GEN_TYPES dialog box, in the Copy To field, enter ZCL_BC402_##_GEN_TYPES and choose Copy. f) In the Create Object Directory Entry dialog box, in the Package field, enter ZBC402_## and choose Save. 2. Analyze the class definition. Which methods are defined? What is their purpose? write_any_struct and write_any_table for list output of any flat structure or any internal table with flat line type.
© Copyright. All rights reserved.
473
Unit 11: Dynamic Programming
3. Which parameters do these methods have? How are the parameters typed? The parameter of method WRITE_ANY_STRUCT is called IS_STRUCT and has TYPE ANY, and the parameter of method WRITE_ANY_TABLE is called IT_TABLE, and has TYPE ANY TABLE. Implement Method write_any_struct Implement method write_any_struct, and output all components of structure gs_struct individually with a WRITE statement by programming a loop in which you access all the components in structure gs_struct consecutively. 1. Create a field symbol (suggested name is ) that has a generic type that allows assignment of any flat components of the structure. a) In the Class Builder, double-click WRITE_ANY_STRUCT and choose Display<->Change. b) See the source code excerpt from the model solution. 2. Program a DO loop. Use the sy-index loop counter to access all components of gs_struct consecutively with the field symbol. a) See the source code excerpt from the model solution. 3. Check whether the field symbol assignment was successful. If it was, output the component with a WRITE statement. Otherwise, exit the loop. a) See the source code excerpt from the model solution. Implement Method write_any_table Implement method write_any_table. Display the contents of internal table it_table in a list by programming a loop. Call your previously implemented method, write_any_struct, for each line. 1. Create a field symbol (suggested name is ) that has a generic type that allows assignment of a line of generic internal table it_table. a) Choose the Back button. b) To write the code, double-click WRITE_ANY_TABLE. c) See the source code excerpt from the model solution. 2. Program a LOOP over internal table it_table. Assign the lines in the internal table to field symbol consecutively. a) See the source code excerpt from the model solution. 3. Call method write_any_struct for each line. a) See the source code excerpt from the model solution. Copy the Template Program Copy program BC402_DYS_DYN_SQL or your own program ZBC402_##_DYN_SQL and name it ZBC402_##_GEN_TYPES, where ## is your group number. Familiarize yourself with the program and how it works. 1. Copy the program and all its subcomponents. a) In SE80, in the unnamed dropdown menu on the left of the screen, choose Program and specify the name of the program ZBC402_##_DYN_SQL.
474
© Copyright. All rights reserved.
Lesson: Using Generic Data Types
b) Choose Display. c) Right-click ZBC402_##_DYN_SQL and choose Copy.... d) In the Copy Program ZBC402_##_DYN_SQL dialog box, in the Target program field, enter ZBC402_##_GEN_TYPES and choose Copy. e) In the Copy Program ZBC402_##_DYN_SQL to ZBC402_##_GEN_TYPES dialog box, select all checkboxes and choose Copy. f) In the Create Object Directory Entry dialog box, in the Package field, enter ZBC402_## and choose Save. 2. Activate and test the program. Analyze the source code. a) Choose the Check button. b) Choose the Activate button. c) Choose the Direct Processing button. Replace a Dynamic Method Call with a Generic Method Replace the dynamic method call at the end of the program with a call of your new method, write_any_table. Remove all parts of the source code you no longer need, or comment them out. 1. Delete the dynamic method call or comment it out. In its place, implement a call of method write_any_table. Pass the method the generic field symbol that points to the internal table with the data. a) See the source code excerpt from the model solution. 2. Delete the definitions of the data objects that are needed for the dynamic method call or comment them out. a) See the source code excerpt from the model solution. 3. Activate and test the program. a) Choose the Check button. b) Choose the Activate button. c) Choose the Direct Processing button. Source code excerpt from the model solution: Method write_any_struct (Class CL_BC402_DYS_GEN_TYPE) method WRITE_ANY_STRUCT. FIELD-SYMBOLS TYPE simple. NEW-LINE. DO. ASSIGN COMPONENT sy-index OF STRUCTURE is_struct TO . IF sy-subrc = 0. WRITE . ELSE. EXIT. ENDIF. ENDDO.
© Copyright. All rights reserved.
475
Unit 11: Dynamic Programming
endmethod. Method write_any_table (Class CL_BC402_DYS_GEN_TYPE) method WRITE_ANY_TABLE. FIELD-SYMBOLS: TYPE ANY. LOOP AT it_table ASSIGNING . write_any_struct( ). ENDLOOP. endmethod. Executable Program BC402_DYS_GEN_TYPES REPORT
bc402_dys_gen_types MESSAGE-ID bc402.
*TYPE-POOLS: abap. DATA: gt_cust gt_conn
TYPE ty_customers, TYPE ty_connections.
*DATA: * gv_methname TYPE string, * gt_parmbind TYPE abap_parmbind_tab, * gs_parmbind TYPE abap_parmbind. DATA: gv_tabname
TYPE string.
FIELD-SYMBOLS: TYPE ANY TABLE. SELECTION-SCREEN COMMENT 1(80) text-sel. PARAMETERS: pa_xconn TYPE xfeld RADIOBUTTON GROUP tab DEFAULT 'X', pa_xcust TYPE xfeld RADIOBUTTON GROUP tab . PARAMETERS: pa_nol TYPE i DEFAULT '100'. START-OF-SELECTION. * specific part *----------------------------------------------------* CASE 'X'. WHEN pa_xconn. gv_tabname = 'SPFLI'. ASSIGN gt_conn TO . WHEN pa_xcust. gv_tabname = 'SCUSTOM'. ASSIGN gt_cust TO . ENDCASE.
476
© Copyright. All rights reserved.
Lesson: Using Generic Data Types
* dynamic part *------------------------------------------------------* TRY.
SELECT * FROM (gv_tabname) INTO TABLE UP TO pa_nol ROWS. CATCH cx_sy_dynamic_osql_error. MESSAGE e061. ENDTRY. * * * * * * * *
TRY.
CALL METHOD cl_bc402_utilities=>(gv_methname) PARAMETER-TABLE gt_parmbind.
CATCH cx_sy_dyn_call_error. MESSAGE e060. ENDTRY. cl_bc402_dys_gen_types=>write_any_table( ).
© Copyright. All rights reserved.
477
Unit 11: Dynamic Programming
Generically Typed Data References You can type reference variables generically. However, in contrast to field symbols, only the generic types DATA (for data references) and OBJECT (for object references) are available for reference variables. The use of generically typed reference variables is restricted in ABAP. With the exception of the ASSIGN statement, generically typed reference variables cannot be dereferenced directly in operand positions. The statement WRITE ref->* causes a syntax error, for example, if the data reference has type TYPE REF TO DATA. Due to these restrictions, only use generic data references where generic field symbols do not work.
Use Cases for Generically Typed Data References Common Use Cases for References with Type TYPE REF TO DATA ●
●
In internal tables (for example, the parameter table for dynamic method and function module calls) During the dynamic generation of data objects using the CREATE DATA statement
Cast Assignment for Data References
Figure 193: Cast Assignment for Data References
To address the content of referenced data objects, one option is to use a fully-typed data reference. The contents of the generic data reference are copied to the fully-typed data reference. The complete data reference can then be dereferenced in any operand item. However, for this technique to work, the second reference variable needs to have the same type as the referenced data object.
478
© Copyright. All rights reserved.
Lesson: Using Generic Data Types
When you assign values between two reference variables with different types, you perform a cast assignment. It is similar to cast assignment between object references in object-oriented programming. As with object references, an upcast occurs when the target variable has a more general definition, and a downcast occurs when the target variable has a more specific type than the source variable. Accordingly, assignment from a generic data reference to a fully typed reference is a downcast. While upcasts to type TYPE REF TO DATA always work, the downcast must have the ?= cast operator to pass the syntax check. The system checks compatibility at runtime in this case.
Caution: If the type of the new reference variable does not match the exact type of the referenced data object, a runtime error occurs. Class-based exception CX_SY_MOVE_CAST_ERROR is the exception that occurs.
Dereferenced Generic Data References
Figure 194: Dereferencing Generically Typed Data References
The only ABAP statement in which you can dereference a generically typed reference variable is the ASSIGN statement. The ASSIGN statement assigns a (generic) field symbol to the data object to which the generic reference variable points. You then address and further process the contents of the referenced object using this field symbol.
© Copyright. All rights reserved.
479
Unit 11: Dynamic Programming
LESSON SUMMARY You should now be able to:
480
●
Explain generic data types of ABAP
●
Use generic data types
●
Access data objects dynamically
●
Use generically typed data references
© Copyright. All rights reserved.
Unit 11 Lesson 2 Describing Data Types, Data Objects, and Objects at Runtime
LESSON OVERVIEW This lesson discusses Runtime Type Identification (RTTI), a technique that you use to query information about data types and object types at runtime. This technique is essential when using the generically typed parameters, field symbols, and references in dynamic programs. Business Example You need to develop a flexible application using generically typed parameters, field symbols, and references. Therefore, you want to learn about the options provided by RTTI for querying information about the actual type of the underlying object at runtime. For this reason, you require the following knowledge: ●
An understanding of how to query the properties of data objects and data types at runtime
●
An understanding of how to query the properties of classes and instances at runtime
LESSON OBJECTIVES After completing this lesson, you will be able to: ●
Explain Runtime Type Identification (RTTI)
●
Describe data types and data objects at runtime
●
Describe object types and objects at runtime
© Copyright. All rights reserved.
481
Unit 11: Dynamic Programming
RTTI Class Hierarchy
Figure 195: Class Hierarchy of RTTI Description Classes
As of SAP Web AS 6.10, ABAP developers can use a class-based concept, RTTI, to determine type properties, such as data types and object types, at runtime. Hint: Before RTTI, ABAP contained only the DESCRIBE FIELD and DESCRIBE TABLE statements. However, these statements are limited to properties of data objects, and do not determine as many properties as RTTI. RTTI consists of a hierarchy of ten global classes that developers use. The description of a type at runtime is realized as an instance of one of these classes. The properties of the type are saved in the instance attributes and can be queried directly or using appropriate methods. At runtime, only one description object exists for each type. All classes inherit properties from a shared superclass, either directly or indirectly, and their names all follow the pattern CL_ABAP_xxxDESCR, where xxx stands for the category of the type used to describe the respective class. Different classes are needed because the attributes and methods of each class relate to a specific category of types. For example, you use class CL_ABAP_TABLEDESCR to describe table types. Therefore, the class contains attributes for the table category and the structure of the table key, among other information. These attributes are specific to class CL_ABAP_TABLEDESCR. No other RTTI classes contain them. RTTI Classes – Purpose Only six of the ten RTTI classes can be instantiated and used to describe specific types.
482
© Copyright. All rights reserved.
Lesson: Describing Data Types, Data Objects, and Objects at Runtime
Table 5: RTTI Classes that can be Instantiated The following table lists the RTTI classes that can be instantiated: RTTI Class
Purpose
CL_ABAP_ELEMDESCR
To describe elementary data types
CL_ABAP_REFDESCR
To describe reference types (= types of reference variables)
CL_ABAP_STRUCTDESCR
To describe structure types
CL_ABAP_TABLEDESCR
To describe table types
CL_ABAP_CLASSDESCR
To describe classes (= object types)
CL_ABAP_INTFDESCR
To describe interfaces
All other RTTI classes are abstract, which means that you cannot instantiate them. They are used to centrally define the attributes and methods that are used in several of the other classes. For example, the METHODS attribute, which contains a list of the methods, is not defined in class CL_ABAP_CLASSDESCR, but instead in class CL_ABAP_OBJECTDESCR, because it is also needed in the same form in class CL_ABAP_INTFDESCR.
RTTI Class Instantiation
Figure 196: RTTI – Methods and Attributes of the Root Class
It is not possible to instantiate the RTTI description classes directly with the CREATE OBJECT statement. To retrieve a reference to a description object, call static method DESCRIBE_BY_xxx of class CL_ABAP_TYPEDESCR. The description objects are generated and the data is filled and returned using a return parameter with generic type REF TO CL_ABAP_TYPEDESCR.
© Copyright. All rights reserved.
483
Unit 11: Dynamic Programming
Describe a Type Based on Its Name
Figure 197: Describing a Type Based on Its Name
After the call, you need to cast to a reference variable of a suitable subclass to access specific attributes and methods for the respective type. If you do not know which RTTI class was instantiated, evaluate the public KIND instance attribute whose contents match the value of one of the six constants from class CL_ABAP_TYPEDESCR. Each of these six constants corresponds to one of the six RTTI classes that the developer can instantiate.
484
© Copyright. All rights reserved.
Lesson: Describing Data Types, Data Objects, and Objects at Runtime
Casting a Suitable Reference for a Type Description Object
Figure 198: Casting a Suitable Reference for a Type Description Object
Hint: If you know which description class is instantiated, then the downcast can also take place directly in the call of the DESCRIBE_BY_xxx functional method, for example, lo_class ?= cl_abap_typedescr=>describe_by_... In this case, it is a good idea to catch runtime error CX_SY_MOVE_CAST_ERROR. Methods for Description Objects The following methods differ with regard to the information they are given in their calls: ●
DESCRIBE_BY_NAME This method returns a description object with which the name of the type is known. It can analyze both data types and object types (classes and interfaces). It is unimportant whether the type was defined globally in the Dictionary or Class Builder, or locally in the program. You must enter the type name in upper case. If the method does not find the type with the specified name, it raises a classic exception TYPE_NOT_FOUND.
●
DESCRIBE_BY_DATA This method returns the description object for the type of a data object. It only returns descriptions of data types, but it does not matter whether the data object is defined with an explicit type or a bound type.
© Copyright. All rights reserved.
485
Unit 11: Dynamic Programming
If the specified data object is a parameter or field symbol with a generic type, the method does not return the description of the generic type. Instead, it returns the type of the currently assigned actual parameter or data object. ●
DESCRIBE_BY_DATA_REF This method returns the description object for the type of a data object that a data reference points to. It only returns descriptions of data types. If the data reference is typed generically (TYPE REF TO DATA), you can use this method to determine the dynamic type of the referenced data object.
Caution: If the reference does not have a valid value at call time, the method raises classic exception REFERENCE_IS_INITIAL.
●
DESCRIBE_BY_OBJECT_REF This method returns the description object for the type of an instance that an object reference points to. It only returns descriptions of classes. Use this method to determine the dynamic type of the referenced instance after an upcast to a superclass or implemented interface.
Caution: If the reference does not have a valid value at call time, the method raises classic exception REFERENCE_IS_INITIAL. Describe Types Based on Data Objects and References
Figure 199: Describing Types Based on Data Objects and References
486
© Copyright. All rights reserved.
Lesson: Describing Data Types, Data Objects, and Objects at Runtime
The figure Describing Types Based on Data Objects and References shows an example of how to use these DESCRIBE_BY_xxx static methods. In addition to the static methods listed, there is another option available for accessing description objects. Special methods are available to navigate from one description object to other description objects. For example, you want to navigate from the description of a table type to the description of the corresponding line type, or you want to navigate from a structure type to the description objects for the component types.
Elementary Data Type Analysis
Figure 200: Analysis of an Elementary Data Type
The example in the figure Analysis of an Elementary Data Type, demonstrates how to use RTTI to determine the properties of different data types, in this case, an elementary data type. The data type determines which subclass is used. An instance of class CL_ABAP_ELEMDESCR describes all the properties of an elementary data type. The corresponding public attributes contain the technical properties of the underlying ABAP type, the length, and the number of decimal places. To evaluate the TYPE_KIND attribute, compare its contents with the corresponding constants from class CL_ABAP_TYPEDESCR, in the same way as for the KIND attribute.
Note: The three attributes are described in the root class of RTTI, which means they are inherited by all description classes. However, in the other classes, these attributes are less significant. The semantic properties, that is, the additional information from the ABAP Dictionary, must be determined explicitly using public methods. The figure shows a call of method
© Copyright. All rights reserved.
487
Unit 11: Dynamic Programming
GET_DDIC_FIELD. You can use an optional parameter to determine language-dependent information, such as field labels, in a language other than the current logon language. Caution: If the current type is not a dictionary type, the method raises a classic exception. To avoid this, first use method IS_DDIC_TYPE to check whether dictionary information is available (see the example given in the figure).
Reference Type Analysis
Figure 201: Analysis of the Type of a Reference Variable
When you analyze a reference type (= type of a reference variable), the inherited TYPE_KIND attribute allows you to differentiate between object references and data references. However, to determine the details of the static type of the reference variable, use the GET_REFERENCED_TYPE navigation method. This method returns a reference to another description object. This description object can be an instance of class CL_ABAP_STRUCTDESCR if the reference variable was created with a structure type. However, if the reference variable was created with reference to a class or an interface, then GET_REFERENCED_TYPE returns instances of the CL_ABAP_CLASSDESCR or CL_ABAP_INTFDESCR class, respectively.
488
© Copyright. All rights reserved.
Lesson: Describing Data Types, Data Objects, and Objects at Runtime
Structure Type Analysis
Figure 202: Analysis of a Structure Type
The CL_ABAP_STRUCTDESCR class also has a number of public attributes with basic information, such as the total length in bytes, the existence of includes, the type of structure (nested or not), and so on. The COMPONENTS attribute is an internal table that contains the names of all components and their elementary technical properties. You can use the GET_DDIC_FIELD_LIST method to determine the semantic information (if any) for the components. It is similar to the GET_DDIC_FIELD method, but returns an internal table instead of a structure.
© Copyright. All rights reserved.
489
Unit 11: Dynamic Programming
Navigation from Structure Type to Component Types
Figure 203: Navigation from Structure Type to Component Types
To gain full access to all properties of the component types, navigate to the respective description objects. The GET_COMPONENT_TYPE navigation method returns the description object for the type of a specific component, while the GET_COMPONENTS navigation method returns the description objects for all components.
Hint: Because component types are also reference types, structure types, or table types, define the return values with type REF TO CL_ABAP_DATADESCR. A downcast to a subclass–typed reference variable may be necessary in reference variables, for example, to type REF TO CL_ABAP_ELEMDESCR.
490
© Copyright. All rights reserved.
Lesson: Describing Data Types, Data Objects, and Objects at Runtime
Table Type Analysis
Figure 204: Analysis of a Table Type
The public attributes of class CL_ABAP_TABLEDESCR include the table type (for example, standard, sorted, hashed, index, or any) uniqueness of the key, and a list of names of the key components. To determine the details for a line type, navigate to a description object for that line type using the GET_TABLE_LINE_TYPE navigation method.
Hint: The line type of a table type can have any data type. Accordingly, the return parameter is typed with REF TO CL_ABAP_DATADESCR, so you might have to perform a downcast to a suitable type if necessary.
© Copyright. All rights reserved.
491
Unit 11: Dynamic Programming
492
© Copyright. All rights reserved.
Unit 11 Exercise 27 Provide Column Headers Using RTTI
Business Example You need to develop a simple program that displays the contents of any database table. To develop the program, you need to find out about the options available in dynamic programming. You have already developed a method to output any internal table with a flat line type to a list. You need to use the options of RTTI to develop a method that generates dynamic column headers for the program. Use RTTI to analyze a structure type and to determine semantic information for that structure type from the ABAP Dictionary. Use the semantic information for the structure type to generate column headers dynamically.
Note: In the exercises for this course, when the input values include ##, replace ## with your group number. Copy Template Class Copy template CL_BC402_DYT_RTTI_HEADERS and name it ZCL_BC402_##_RTTI_HEADERS. Familiarize yourself with the class definition. 1. Copy the global class. 2. Analyze the class definition. Determine which methods are defined and what their purposes are?
3. Which parameters and exceptions do these methods have? How are the parameters typed? Which error situations correspond to the exceptions?
Implement Method write_headers Implement method write_headers. Use RTTI options to analyze the Dictionary table whose name is passed to the import parameter gv_tabname. 1. Call a suitable static method of class CL_ABAP_TYPEDESCR to analyze the data type based on its name.
© Copyright. All rights reserved.
493
Unit 11: Dynamic Programming
2. Create a local reference variable (suggested name is lo_type) and type it to match the return parameter of the method. Specify this reference variable as an actual parameter in the method call. 3. Handle any possible exceptions and raise exception TYPE_NOT_FOUND from method write_headers in response. 4. Use the public KIND attribute to determine whether the generated RTTI instance actually describes a structure type. If the data type is not a structure type, exit method write_headers with exception NO_STRUCTURE. 5. Create a local reference variable (suggested name is lo_struct) of TYPE REF TO CL_ABAP_STRUCTDESCR. Program a down cast to point this reference to the type description object. Hint: There is no need to catch possible runtime errors here because the query of the KIND attribute already ensures compatibility. Output the Report Header for all Components Determine a list with dictionary information for all components of the structure type. Output the report header for all components in sequence. Ensure that the output does not exceed the display length of the corresponding field. 1. Create an internal table with type ddfields (suggested name: lt_fields). 2. Call a suitable method of class CL_ABAP_STRUCTDESCR to generate a list with dictionary information for the structure components. To do so, supply the internal table it_fields as the actual parameter for the return value. If the method call terminates with exceptions, exit the write_headers method with a suitable exception. 3. To program a loop over the internal table, create a field symbol (suggested name is ) that is typed with the line type of internal table lt_fields. 4. Output the report header (field reptext) in each loop pass. Use the output length (field outputlen) for length access to ensure the headers are exactly as long as they will be output later. Copy Template Program Copy program BC402_DYS_GEN_TYPES or your own program, ZBC402_##_GEN_TYPES and name it ZBC402_##_RTTI_HEADERS. Familiarize yourself with the program and how it works. 1. Copy the program and all its subcomponents. 2. Activate and test the program. Analyze the source code. Call Method write_headers Insert a call of method write_headers before the data output. Pass the name of the line type of the internal table with the data to your method. 1. Implement a call of method write_headers before the call of method write_any_table. Pass the data object that contains the name of the database table (and therefore the name of the line type of the internal table). 2. React to exceptions with suitable error messages from message class BC402.
494
© Copyright. All rights reserved.
Lesson: Describing Data Types, Data Objects, and Objects at Runtime
3. Activate and test the program.
© Copyright. All rights reserved.
495
Unit 11 Solution 27 Provide Column Headers Using RTTI
Business Example You need to develop a simple program that displays the contents of any database table. To develop the program, you need to find out about the options available in dynamic programming. You have already developed a method to output any internal table with a flat line type to a list. You need to use the options of RTTI to develop a method that generates dynamic column headers for the program. Use RTTI to analyze a structure type and to determine semantic information for that structure type from the ABAP Dictionary. Use the semantic information for the structure type to generate column headers dynamically.
Note: In the exercises for this course, when the input values include ##, replace ## with your group number. Copy Template Class Copy template CL_BC402_DYT_RTTI_HEADERS and name it ZCL_BC402_##_RTTI_HEADERS. Familiarize yourself with the class definition. 1. Copy the global class. a) To start the Object Navigator, enter transaction code se80. b) In the unnamed dropdown menu on the left of the screen, choose Class/Interface and specify the name of the class CL_BC402_DYT_RTTI_HEADERS. c) Choose Display. d) Right-click CL_BC402_DYT_RTTI_HEADERS and choose Copy.... e) In the Copy CL_BC402_DYT_RTTI_HEADERS dialog box, in the Copy to field, enter ZCL_BC402_##_RTTI_HEADERS and choose Copy. f) In the Create Object Directory Entry dialog box, in the Package field, enter ZBC402_## and choose Save. 2. Analyze the class definition. Determine which methods are defined and what their purposes are? write_headers to output a list of column headers based on a structure type from the ABAP Dictionary.
496
© Copyright. All rights reserved.
Lesson: Describing Data Types, Data Objects, and Objects at Runtime
3. Which parameters and exceptions do these methods have? How are the parameters typed? Which error situations correspond to the exceptions? Parameter iv_tabname with generic type csequence and exceptions. Error situations that correspond to the exceptions are as follows: TYPE_NOT_FOUND: the supplied type is unknown, NO_STRUCTURE: the object is not a structure type, NO_DDIC_TYPE: the object is not a type in the ABAP Dictionary. Implement Method write_headers Implement method write_headers. Use RTTI options to analyze the Dictionary table whose name is passed to the import parameter gv_tabname. 1. Call a suitable static method of class CL_ABAP_TYPEDESCR to analyze the data type based on its name. a) In the Methods tab, double-click WRITE_HEADERS and choose Display<->Change. b) See the source code excerpt from the model solution. 2. Create a local reference variable (suggested name is lo_type) and type it to match the return parameter of the method. Specify this reference variable as an actual parameter in the method call. a) See the source code excerpt from the model solution. 3. Handle any possible exceptions and raise exception TYPE_NOT_FOUND from method write_headers in response. a) See the source code excerpt from the model solution. 4. Use the public KIND attribute to determine whether the generated RTTI instance actually describes a structure type. If the data type is not a structure type, exit method write_headers with exception NO_STRUCTURE. a) See the source code excerpt from the model solution. 5. Create a local reference variable (suggested name is lo_struct) of TYPE REF TO CL_ABAP_STRUCTDESCR. Program a down cast to point this reference to the type description object. Hint: There is no need to catch possible runtime errors here because the query of the KIND attribute already ensures compatibility. a) See the source code excerpt from the model solution. Output the Report Header for all Components Determine a list with dictionary information for all components of the structure type. Output the report header for all components in sequence. Ensure that the output does not exceed the display length of the corresponding field. 1. Create an internal table with type ddfields (suggested name: lt_fields). a) See the source code excerpt from the model solution. 2. Call a suitable method of class CL_ABAP_STRUCTDESCR to generate a list with dictionary information for the structure components. To do so, supply the internal table it_fields as
© Copyright. All rights reserved.
497
Unit 11: Dynamic Programming
the actual parameter for the return value. If the method call terminates with exceptions, exit the write_headers method with a suitable exception. a) See the source code excerpt from the model solution. 3. To program a loop over the internal table, create a field symbol (suggested name is ) that is typed with the line type of internal table lt_fields. a) See the source code excerpt from the model solution. 4. Output the report header (field reptext) in each loop pass. Use the output length (field outputlen) for length access to ensure the headers are exactly as long as they will be output later. a) See the source code excerpt from the model solution. Copy Template Program Copy program BC402_DYS_GEN_TYPES or your own program, ZBC402_##_GEN_TYPES and name it ZBC402_##_RTTI_HEADERS. Familiarize yourself with the program and how it works. 1. Copy the program and all its subcomponents. a) In SE80, in the unnamed dropdown menu on the left of the screen, choose Program and specify the name of the program ZBC402_##_GEN_TYPES. b) Choose Display. c) Right-click ZBC402_##_GEN_TYPES and choose Copy.... d) In the Copy Program ZBC402_##_GEN_TYPES dialog box, in the Target program field, enter ZBC402_##_RTTI_HEADERS and choose Copy. e) In the Copy Program ZBC402_##_GEN_TYPES to ZBC402_##_RTTI_HEADERS dialog box, select all checkboxes and choose Copy. f) In the Create Object Directory Entry dialog box, in the Package field, enter ZBC402_## and choose Save. 2. Activate and test the program. Analyze the source code. a) Choose the Check button. b) Choose the Activate button. c) Choose the Direct Processing button. Call Method write_headers Insert a call of method write_headers before the data output. Pass the name of the line type of the internal table with the data to your method. 1. Implement a call of method write_headers before the call of method write_any_table. Pass the data object that contains the name of the database table (and therefore the name of the line type of the internal table). a) See the source code excerpt from the model solution. 2. React to exceptions with suitable error messages from message class BC402. a) See the source code excerpt from the model solution. 3. Activate and test the program. a) Choose the Check button.
498
© Copyright. All rights reserved.
Lesson: Describing Data Types, Data Objects, and Objects at Runtime
b) Choose the Activate button. c) Choose the Direct Processing button. Source code excerpt from the model solution: Method write_headers (Class_CL_BC402_DYS_RTTI_HEADERS) METHOD write_headers. DATA: lo_type TYPE REF TO cl_abap_typedescr, lo_struct TYPE REF TO cl_abap_structdescr, lt_flist TYPE ddfields. FIELD-SYMBOLS: LIKE LINE OF lt_flist. CALL METHOD cl_abap_typedescr=>describe_by_name EXPORTING p_name = iv_tabname RECEIVING p_descr_ref = lo_type EXCEPTIONS type_not_found = 1. IF sy-subrc <> 0. RAISE type_not_found. ENDIF. IF lo_type->kind <> cl_abap_typedescr=>kind_struct. RAISE no_structure. ENDIF. lo_struct ?= lo_type. CALL METHOD lo_struct->get_ddic_field_list RECEIVING p_field_list = lt_flist EXCEPTIONS not_found = 1 no_ddic_type = 2. CASE sy-subrc. WHEN 1. RAISE type_not_found. WHEN 2. RAISE no_ddic_type. ENDCASE. NEW-LINE. LOOP AT lt_flist ASSIGNING . WRITE -reptext(-outputlen) COLOR COL_HEADING. ENDLOOP. ULINE. ENDMETHOD.
© Copyright. All rights reserved.
499
Unit 11: Dynamic Programming
Executable Program BC402_DYS_RTTI_HEADERS REPORT
bc402_dys_rtti_headers MESSAGE-ID bc402.
TYPE-POOLS: abap. DATA: gt_cust gt_conn DATA: gv_tabname
TYPE ty_customers, TYPE ty_connections. TYPE string.
FIELD-SYMBOLS: TYPE ANY TABLE. SELECTION-SCREEN COMMENT 1(80) text-sel. PARAMETERS: pa_xconn TYPE xfeld RADIOBUTTON GROUP tab DEFAULT 'X', pa_xcust TYPE xfeld RADIOBUTTON GROUP tab . PARAMETERS: pa_nol TYPE i DEFAULT '100'. START-OF-SELECTION. * specific part *----------------------------------------------------* CASE 'X'. WHEN pa_xconn. gv_tabname = 'SPFLI'. ASSIGN gt_conn TO . WHEN pa_xcust. gv_tabname = 'SCUSTOM'. ASSIGN gt_cust TO . ENDCASE. * dynamic part *------------------------------------------------------* TRY.
SELECT * FROM (gv_tabname) INTO TABLE UP TO pa_nol ROWS. CATCH cx_sy_dynamic_osql_error. MESSAGE e061. ENDTRY. CALL METHOD cl_bc402_dys_rtti_headers=>write_headers EXPORTING iv_tabname = gv_tabname EXCEPTIONS type_not_found = 1 no_structure = 2 no_ddic_type = 3. CASE sy-subrc. WHEN 1.
500
© Copyright. All rights reserved.
Lesson: Describing Data Types, Data Objects, and Objects at Runtime
MESSAGE e050 WITH gv_tabname. WHEN 2. MESSAGE e051 WITH gv_tabname. WHEN 3. MESSAGE e052 WITH gv_tabname. ENDCASE. cl_bc402_dys_gen_types=>write_any_table( ).
© Copyright. All rights reserved.
501
Unit 11: Dynamic Programming
Object Type Analysis
Figure 205: Analysis of an Object Type
RTTI permits you to analyze the attributes of objects by working with classes CL_ABAP_CLASSDESCR and CL_ABAP_INTFDESCR. Most of the attributes and methods for these two classes are defined in the (abstract) shared superclass CL_ABAP_OBJECTDESCR because they are required to analyze both classes and interfaces.
Note: A class is analyzed in the example shown in the figure Analysis of an Object Type. Most of the information also applies to the analysis of interfaces. Class CL_ABAP_CLASSDESCR contains public attributes that list the attributes, methods, events, interfaces, and other objects of the described class. These attributes are typed as internal tables. Some of these attributes, such as METHODS, are defined as nested internal tables in which each line itself contains one or more internal tables. For example, these nested internal tables contain lists with parameters and exceptions for the respective method. In addition to these inherited attributes, class CL_ABAP_CLASSDESCR also provides specific attributes, such as the CLASS_KIND attribute, which you use to determine whether the class was flagged as abstract, final, and so on.
Note: Class CL_ABAP_INTFDESCR contains an INTF_KIND attribute instead, which you use to determine whether an interface is comprised of multiple interfaces.
502
© Copyright. All rights reserved.
Lesson: Describing Data Types, Data Objects, and Objects at Runtime
The figure Analysis of an Object Type demonstrates how to use RTTI to determine all the parameters of the constructor for class CL_RENTAL. After the program generates the description object and performs the downcast, it reads the description of the constructor method from the list of methods (statement with READ TABLE). The program then evaluates the list of parameters for the constructor method in a loop (LOOP over the inner internal table). The description classes for object types also provide navigation methods for determining the details of a used type. For example, the GET_ATTRIBUTE_TYPE method returns the description object for the type of a specific attribute, while GET_METHOD_PARAMETER_TYPE analyzes the type of a specific method parameter, and so on. The GET_SUPER_CLASS_TYPE method is specific to classes. It returns the description object for the direct superclass, if any.
© Copyright. All rights reserved.
503
Unit 11: Dynamic Programming
LESSON SUMMARY You should now be able to:
504
●
Explain Runtime Type Identification (RTTI)
●
Describe data types and data objects at runtime
●
Describe object types and objects at runtime
© Copyright. All rights reserved.
Unit 11 Lesson 3 Creating Data Types, Data Objects, and Objects at Runtime
LESSON OVERVIEW In this lesson, you will learn how to generate data objects (as instances of data types) at runtime, which is similar to creating instances of classes in object-oriented programming. In contrast to data objects that are created statically with the DATA statement, you do not have to directly set the type of dynamically generated data objects. Instead, the type can be determined dynamically at runtime. You will also learn about Runtime Type Creation (RTTC), a technique that lets you define the data type at runtime. Business Example You need to develop a flexible application. In addition to accessing existing data objects dynamically and analyzing the underlying data types, you also want to learn about the techniques available to generate objects, data objects, and data types at runtime according to the requirements of the program. For this reason, you require the following knowledge: ●
An understanding of how to generate objects or instances at runtime
●
An understanding of how to generate data objects at runtime
●
An understanding of how to generate data types at runtime
LESSON OBJECTIVES After completing this lesson, you will be able to: ●
Create objects at runtime
●
Create data objects at runtime
●
Create data types at runtime
© Copyright. All rights reserved.
505
Unit 11: Dynamic Programming
Dynamic Object Creation
Figure 206: Options for Generating Objects at Runtime
The CREATE OBJECT statement generates objects or specifically, instances of classes at runtime. Usually, the type of object, (that is, the class to be instantiated) is defined implicitly through the static type of the reference variable used. Alternatively, you can use the TYPE addition to specify the class to be instantiated in the CREATE OBJECT statement. The following rules apply when using the TYPE addition of the CREATE OBJECT statement: ●
●
●
A class, not an interface, must appear after the TYPE addition. You must be able to instantiate the class, which means that it cannot be flagged as abstract. The static type of the reference variable must be compatible with the class.
The last rule applies because the system carries out an implicit upcast if necessary when you specify the type explicitly. The reference variable is compatible with the created object if it meets one of the following conditions: ●
The reference variable is typed with the class to be instantiated.
●
The reference variable is typed with a superclass of the class to be instantiated.
●
●
The reference variable is typed with an interface that is implemented by the class to be instantiated. The reference variable is typed with the generic TYPE REF TO OBJECT.
The syntax for specifying an explicit type can include a data object in parentheses after TYPE. This syntax enables dynamic selection of the class to be instantiated.
506
© Copyright. All rights reserved.
Lesson: Creating Data Types, Data Objects, and Objects at Runtime
Hint: If classes are available for selections that are not linked through a shared superclass or the same implementing interface, type the reference variable completely generically with TYPE REF TO OBJECT.
Dynamic Parameter Passing
Figure 207: Dynamic Passing of Parameters
If all potential classes have the same constructor signature, the parameters can be supplied with data statically. However, it is likely that the parameters and exceptions of the constructors will differ. In this case, you need to use dynamic parameter transfer. As with dynamic method calls, perform dynamic parameter transfer using internal tables after the PARAMETER-TABLE and EXCEPTION-TABLE additions. These internal tables need to be typed and filled just like with dynamic method calls.
© Copyright. All rights reserved.
507
Unit 11: Dynamic Programming
Dynamic Data Object Creation
Figure 208: Options for Creating Data Objects at Runtime
You can also create data objects at runtime. The corresponding statement, CREATE DATA, is used in a similar way to the CREATE OBJECT statement. The CREATE DATA statement creates a data object dynamically, assigns memory to it, and points the data reference variable to that data object in memory. The data object is not given a name, so it is often called an anonymous data object. To address the data object, dereference the reference variable at runtime.
Hint: In contrast to the static DATA declaration, the system does not reserve the memory for the data objects until runtime, and it does not reserve the memory when the respective program is loaded. Like with class instances, the garbage collector releases the memory again as soon as the program deletes the last reference to the data object. As with CREATE OBJECT, you can define the type of the data object implicitly by using the type of the reference variable, or explicitly by using the TYPE addition. If you use explicit typing, you can use a number of variants that you might be familiar with from DATA declarations. These variants include the use of built-in types, the implicit construction of table types, and the reference to an existing data object with LIKE. To define the data type for the generated data objects dynamically, use character-type data objects in parentheses.
508
© Copyright. All rights reserved.
Lesson: Creating Data Types, Data Objects, and Objects at Runtime
Note: Alternatively, use the TYPE HANDLE addition to refer to an RTTI-type description object.
Access to Dynamically Created Data Objects
Figure 209: Access to Dynamically Created Data Objects
If the data type is to be determined dynamically, the reference variable must be typed generically with TYPE REF TO DATA. This is the only generic type that can be used for data references at present. Reasons for Assigning Field Symbols to the Referenced Data Object ●
You can only dereference the generic data reference in the ASSIGN statement.
●
You can use generically typed field symbols almost anywhere.
Hint: If the new data object is an internal table and you want to use it in the corresponding operand positions, the field symbol must contain at least type ANY TABLE. Dynamically Generated Internal Table and Dynamic SELECT
Figure 210: Example – Dynamically Generated Internal Table and Dynamic SELECT
© Copyright. All rights reserved.
509
Unit 11: Dynamic Programming
The figure Example – Dynamically Generated Internal Table and Dynamic SELECT shows an example of a dynamic database access in which the suitable data object is generated at runtime.
510
© Copyright. All rights reserved.
Unit 11 Exercise 28 Create Data Objects at Runtime
Business Example You need to develop a simple program that displays the contents of any database table by using the options available in dynamic programming.
Note: The program you created in the exercise Provide Column Headers Using RTTI can already output the content of any internal table in a list. The database access (the SELECT statement) has a dynamic design. At this point, there is one more condition that hinders you from reading any table: The data objects that you fill in the SELECT statement must have static definitions. In this exercise, you generate data objects dynamically at runtime. This enables your program to read and display the content of any database table.
Note: In the exercises for this course, when the input values include ##, replace ## with your group number.
Copy Template Program Copy program BC402_DYS_RTTI_HEADERS or your own program, ZBC402_##_RTTI_HEADERS and name it ZBC402_##_CREATE_DATA. Familiarize yourself with the program and how it works. 1. Copy the program and all its subcomponents. 2. Activate and test the program. 3. Analyze the source code. Which data objects are filled during the database access? Which types do they have? Were they created statically or dynamically?
Create an Internal Table at Runtime Replace the two statically defined internal tables with a data object that you generate after the CASE structure (standard table with non-unique standard key). Define the type of the data object dynamically to ensure that the line type precisely matches the structure of the database table you want to read. 1. Define a generically typed data reference (suggested name is gr_data).
© Copyright. All rights reserved.
511
Unit 11: Dynamic Programming
2. Use the gr_data data reference to generate an internal table immediately after the ENDCASE statement. Access the contents of data object gv_tabname to define the line type of the table dynamically. 3. Move one of the ASSIGN statements outside the WHEN blocks after the data object is generated, and delete the other ASSIGN statement. Replace the statically defined internal table with the dynamically generated table. Hint: Dereference the generic data reference.
4. Why can you not continue to use gr_data directly?
5. Delete the definitions of the two static internal tables or comment them out. 6. Activate and test your program. Allow Any Database Table to be Selected by the User The static part of the program now contains only the filling of data object gv_tabname with an appropriate literal for the name of the database table. Replace both checkboxes on the selection screen with a parameter for the name of any database table. 1. Delete the selection screen parameter definitions for the two checkboxes, or comment them out. 2. Create a new parameter (suggested name is pa_tab). Hint: If you use the global type dd02l-tabname, a value (F4) help function is provided for the users. 3. Delete the CASE structure or comment it out. In the same position, program a value assignment from pa_tab to gv_tabname. 4. Activate and test your program.
512
© Copyright. All rights reserved.
Unit 11 Solution 28 Create Data Objects at Runtime
Business Example You need to develop a simple program that displays the contents of any database table by using the options available in dynamic programming.
Note: The program you created in the exercise Provide Column Headers Using RTTI can already output the content of any internal table in a list. The database access (the SELECT statement) has a dynamic design. At this point, there is one more condition that hinders you from reading any table: The data objects that you fill in the SELECT statement must have static definitions. In this exercise, you generate data objects dynamically at runtime. This enables your program to read and display the content of any database table.
Note: In the exercises for this course, when the input values include ##, replace ## with your group number.
Copy Template Program Copy program BC402_DYS_RTTI_HEADERS or your own program, ZBC402_##_RTTI_HEADERS and name it ZBC402_##_CREATE_DATA. Familiarize yourself with the program and how it works. 1. Copy the program and all its subcomponents. a) To start the Object Navigator, enter transaction code se80. b) In the unnamed dropdown menu on the left of the screen, choose Program and specify the name of the program ZBC402_##_RTTI_HEADERS. c) Choose Display. d) Right-click ZBC402_##_RTTI_HEADERS and choose Copy.... e) In the Copy Program ZBC402_##_RTTI_HEADERS dialog box, in the Target program field, enter ZBC402_##_CREATE_DATA and choose Copy. f) In the Copy Program ZBC402_##_RTTI_HEADERS to ZBC402_##_CREATE_DATA dialog box, select all checkboxes and choose Copy. g) In the Create Object Directory Entry dialog box, in the Package field, enter ZBC402_## and choose Save.
© Copyright. All rights reserved.
513
Unit 11: Dynamic Programming
2. Activate and test the program. a) Choose the Check button. b) Choose the Activate button. c) Choose the Direct Processing button. 3. Analyze the source code. Which data objects are filled during the database access? Which types do they have? Were they created statically or dynamically? One of two internal tables, gt_conn or gt_cust, is filled depending on the user entry. While the data object assigned to field symbol (which is therefore addressed in the SELECT statement) is determined dynamically, the data objects themselves have static definitions (DATA statement). Create an Internal Table at Runtime Replace the two statically defined internal tables with a data object that you generate after the CASE structure (standard table with non-unique standard key). Define the type of the data object dynamically to ensure that the line type precisely matches the structure of the database table you want to read. 1. Define a generically typed data reference (suggested name is gr_data). a) See the source code excerpt from the model solution. 2. Use the gr_data data reference to generate an internal table immediately after the ENDCASE statement. Access the contents of data object gv_tabname to define the line type of the table dynamically. a) See the source code excerpt from the model solution. 3. Move one of the ASSIGN statements outside the WHEN blocks after the data object is generated, and delete the other ASSIGN statement. Replace the statically defined internal table with the dynamically generated table. Hint: Dereference the generic data reference.
a) See the source code excerpt from the model solution. 4. Why can you not continue to use gr_data directly? Because gr_data has a generic type and ABAP only allows dereferenced access to generically typed data references in ASSIGN statements. 5. Delete the definitions of the two static internal tables or comment them out. a) See the source code excerpt from the model solution. 6. Activate and test your program. a) Choose the Check button. b) Choose the Activate button. c) Choose the Direct Processing button.
514
© Copyright. All rights reserved.
Lesson: Creating Data Types, Data Objects, and Objects at Runtime
Allow Any Database Table to be Selected by the User The static part of the program now contains only the filling of data object gv_tabname with an appropriate literal for the name of the database table. Replace both checkboxes on the selection screen with a parameter for the name of any database table. 1. Delete the selection screen parameter definitions for the two checkboxes, or comment them out. a) See the source code excerpt from the model solution. 2. Create a new parameter (suggested name is pa_tab). Hint: If you use the global type dd02l-tabname, a value (F4) help function is provided for the users. a) See the source code excerpt from the model solution. 3. Delete the CASE structure or comment it out. In the same position, program a value assignment from pa_tab to gv_tabname. a) See the source code excerpt from the model solution. 4. Activate and test your program. a) Choose the Check button. b) Choose the Activate button. c) Choose the Direct Processing button. Source code excerpt from the model solution: *&--------------------------------------* *& Report BC402_DYS_CREATE_DATA *& *&--------------------------------------* *& *& *&--------------------------------------* REPORT bc402_dys_create_data MESSAGE-ID bc402. *DATA: * gt_cust TYPE ty_customers, * gt_conn TYPE ty_connections. DATA: gr_data TYPE REF TO data. DATA: gv_tabname TYPE string. FIELD-SYMBOLS: TYPE ANY TABLE. SELECTION-SCREEN COMMENT 1(80) text-sel. *PARAMETERS: * pa_xconn TYPE xfeld RADIOBUTTON GROUP tab DEFAULT 'X', * pa_xcust TYPE xfeld RADIOBUTTON GROUP tab . PARAMETERS pa_tab TYPE dd02l-tabname DEFAULT 'SPFLI'. PARAMETERS:
© Copyright. All rights reserved.
515
Unit 11: Dynamic Programming
pa_nol
TYPE i DEFAULT '100'.
START-OF-SELECTION. * specific part *---------------------------------* * CASE 'X'. * WHEN pa_xconn. * * gv_tabname = 'SPFLI'. * ASSIGN gt_conn TO . * * WHEN pa_xcust. * * gv_tabname = 'SCUSTOM'. * ASSIGN gt_cust TO . * * ENDCASE. * dynamic part *---------------------------------* gv_tabname = pa_tab. CREATE DATA gr_data TYPE TABLE OF (gv_tabname). ASSIGN gr_data->* TO . TRY. SELECT * FROM (gv_tabname) INTO TABLE UP TO pa_nol ROWS. CATCH cx_sy_dynamic_osql_error. MESSAGE e061. ENDTRY. CALL METHOD cl_bc402_dys_rtti_headers=>write_headers EXPORTING iv_tabname = gv_tabname EXCEPTIONS type_not_found = 1 no_structure = 2 no_ddic_type = 3. CASE sy-subrc. WHEN 1. MESSAGE e050 WITH gv_tabname. WHEN 2. MESSAGE e051 WITH gv_tabname. WHEN 3. MESSAGE e052 WITH gv_tabname. ENDCASE. cl_bc402_dys_gen_types=>write_any_table( ).
516
© Copyright. All rights reserved.
Lesson: Creating Data Types, Data Objects, and Objects at Runtime
Runtime Type Creation (RTTC)
Figure 211: Dynamic Type Creation Methods of Runtime Type Services
RTTI enables you to describe data types and object types with instances of RTTI classes or type description objects. The RTTI concept was enhanced in SAP Web AS 6.40. In addition to describing existing types, you can use it to generate new types. This enhanced function set is called runtime type creation (RTTC). RTTC consists of a number of additional static methods in the RTTI description classes.
Hint: Note that type generation is restricted to data types. You cannot generate classes or interfaces dynamically. In the figure Dynamic Type Creation Methods of Runtime Type Services, the CL_ABAP_REFDESCR, CL_ABAP_STRUCTDESCR, and CL_ABAP_TABLEDESCR classes are enhanced with a CREATE method, while the CL_ABAP_ELEMDESCR class receives an appropriate GET method for each built-in elementary ABAP type such as, GET_I, GET_F, GET_C, GET_STRING. These methods return pointers to an instance of the respective class. In contrast to the DESCRIBE methods of the root class, the attribute values of this instance do not come from analyzing a data object, a reference, or a named type. Instead, they are passed on to the RTTC method explicitly. The method signatures have been designed accordingly. While the GET_I method does not need any other input (type i is complete), method GET_P has two import parameters defined: one for length and the other for the number of decimal places. The CREATE method for reference types expects the pointer to the description object for the referenced type, while the CREATE method for structure types expects a list with names and
© Copyright. All rights reserved.
517
Unit 11: Dynamic Programming
types of the components. When table types are generated, a reference to an RTTI object that describes the line type is expected (among other things).
Dynamic Table Type Creation
Figure 212: RTTC – Creating a Table Type
The figure RTTC – Creating a Table Type shows how to generate a table type dynamically with RTTC. You are required to specify only the P_LINE_TYPE parameter for the CREATE method. The parameter is of type REF TO CL_ABAP_DATADESCR and needs to be supplied with a reference to any description object for a data type. In the example shown in the figure RTTC – Creating a Table Type, SPFLI is used as the line type. The DESCRIBE_BY_NAME method returns the matching description object. The optional parameters are used to define the table type and key. If you do not specify them, a standard table with a non-unique standard key is used by default.
518
© Copyright. All rights reserved.
Lesson: Creating Data Types, Data Objects, and Objects at Runtime
Use of RTTC Types
Figure 213: Generating an Internal Table with a Dynamically Created Type
To dynamically create a data object with this specific type, use the dynamically generated type in the CREATE DATA statement. Use the HANDLE addition with the CREATE DATA statement to generate a data object whose type matches the specified type description object. Specify the HANDLE as a reference variable with static type CL_ABAP_DATADESCR or one of its subclasses. The type object may have been created based on existing data types, using RTTI methods or by dynamically defining a new data type.
© Copyright. All rights reserved.
519
Unit 11: Dynamic Programming
520
© Copyright. All rights reserved.
Unit 11 Exercise 29 Create Data Types at Runtime with RTTC
Business Example You have developed a simple program that displays the contents of any database table. The program now needs to allow users to select the specific columns they want to read and display. You should use function module BC402_SELECT_COMPONENTS, which displays all the components of a global structure type and enables users to select components. You then need to use RTTC to generate a table type dynamically, with a line type containing only the user-selected components.
Note: In the exercises for this course, when the input values include ##, replace ## with your group number. Analyze Function Module BC402_SELECT_COMPONENTS Display function module BC402_SELECT_COMPONENTS. Analyze the interface and test the functional scope of the function module. 1. Display the function module. 2. Analyze the interface. Which parameters are there and what are their types?
3. Which exceptions can the function module raise, and what purpose do they serve?
4. Test the function module using table SPFLI. Call Function Module BC402_SELECT_COMPONENTS Copy program BC402_DYS_CREATE_DATA or your own program ZBC402_##_CREATE_DATA and name it ZBC402_##_RTTC. Familiarize yourself with the program and how it works. Implement a call of the function module before the dynamic generation of the data object. Pass the table name that the user entered on the selection screen to the import parameter. 1. Copy the program and all its subcomponents. 2. Call the function module before the CREATE DATA statement. Create a suitably typed data object to import the data from the function module parameter ET_COMP_NAMES. Pass
© Copyright. All rights reserved.
521
Unit 11: Dynamic Programming
the contents of gv_tabname to the import parameter. React to exceptions with suitable error messages from message class BC402. Copy the Template Class Copy the template class CL_BC402_DYT_RTTC and name it ZCL_BC402_##_RTTC. Familiarize yourself with the signature of method create_table_type. 1. Copy the global class. 2. Analyze the create_table_type method signature. Which parameters are defined? How are they typed?
Implement the create_table_type Method Use RTTI techniques to analyze the data type of the database table name contained in the import parameter. Use a suitable navigation method to create a list with the names and RTTI type description objects for all components in the structure. 1. Call a suitable method of class CL_ABAP_TYPEDESCR to generate a type description object for the data type. Create a reference variable with a suitable type for the return value (suggested name: lo_struct). Hint: For simplicity, assume that the data type is a structure type in the ABAP Dictionary and perform a direct down cast to the corresponding reference variable. 2. Call the get_components method for the RTTI instance. Create a data object with a suitable type for the return value (suggested name is lt_comps). Create a Table Type Description Object with Only the Required Components Change the list of components so that it only contains the components listed in import parameter it_comp_names. Based on this list of components, create a new structure type, and then a new table type. 1. Implement a loop over the lt_comps component list. 2. Check whether the component name in each line is contained in import parameter it_comp_names. Hint: Use a statement such as FIND ... IN TABLE or READ TABLE ... TRANSPORTING NO FIELDS. 3. Remove the current line from lt_comps if the corresponding table name is not contained in import parameter it_comp_names.
522
© Copyright. All rights reserved.
Lesson: Creating Data Types, Data Objects, and Objects at Runtime
Hint: Use the abbreviated syntax for index access in loops here.
4. To generate an RTTI type description object for a new structure type, call the CREATE method of class CL_ABAP_STRUCTDESCR. Pass the reduced component list to the method. Create a data object with a suitable type for the return parameter (suggested name: lo_struct_new). 5. To generate an RTTI type description object for a new table type, call the CREATE method of class CL_ABAP_TABLEDESCR. Pass the reference to the RTTI object for the new structure type. Leave all the optional parameters set to their default values. Transfer the result of the method call directly to return parameter ro_table_def of method create_table_type. Call an Internal Table at Runtime with Only the Required Components Go back to your executable program ZBC402_##_RTTC. Call method create_table_type to generate a table type according to the requirements of the user. Use the new data type when you generate the data object dynamically. Change the SELECT statement so that it reads only those fields from the database that are contained in the line type of the internal table. Hint: Method write_headers still outputs the headers for all the columns in the table. Either work without the headers completely or use method write_headers_by_data from class CL_BC402_DYS_RTTI_HEADERS. This method analyzes the actual line type of an internal table and outputs the column headers for it. 1. Call method create_table_type in the program directly after the call of function module BC402_SELECT_COMPONENTS. Pass the name of the database table and the list of components that the user selected to the method create_table_type. 2. Change the type in the CREATE DATA statement. Use the TYPE HANDLE addition to use the newly generated table type. 3. Change the SELECT statement. Use the list of component names as a dynamic field list. Hint: Alternatively, use the INTO CORRESPONDING FIELDS OF TABLE addition.
4. Activate and test your program.
© Copyright. All rights reserved.
523
Unit 11 Solution 29 Create Data Types at Runtime with RTTC
Business Example You have developed a simple program that displays the contents of any database table. The program now needs to allow users to select the specific columns they want to read and display. You should use function module BC402_SELECT_COMPONENTS, which displays all the components of a global structure type and enables users to select components. You then need to use RTTC to generate a table type dynamically, with a line type containing only the user-selected components.
Note: In the exercises for this course, when the input values include ##, replace ## with your group number. Analyze Function Module BC402_SELECT_COMPONENTS Display function module BC402_SELECT_COMPONENTS. Analyze the interface and test the functional scope of the function module. 1. Display the function module. a) To start the Object Navigator, enter transaction code se80. b) Choose the Other Object... button. c) In the Object Selection dialog box, select the Enhanced Options radio button. d) Choose the Function Group tab and select the Function Module radio button. e) In the Function Module field, enter BC402_SELECT_COMPONENTS and choose Continue. 2. Analyze the interface. Which parameters are there and what are their types? There is one import parameter, iv_tabname, with type csequence and one export parameter, et_comp_names, with type string_table (standard table with string line type). 3. Which exceptions can the function module raise, and what purpose do they serve? The exceptions raised by the function module and the purposes served by those exceptions are as follows: TYPE_NOT_FOUND: the passed type is unknown, NO_STRUCTURE: the passed type is not a structure, NO_DDIC_TYPE: the passed type is not a DDIC type. 4. Test the function module using table SPFLI.
524
© Copyright. All rights reserved.
Lesson: Creating Data Types, Data Objects, and Objects at Runtime
a) Choose the Test/Execute button. b) In the Value field next to the parameter IV_TABNAME, enter SPFLI. c) Choose Execute. d) To select a few rows, select the button to the left of the first row, and, on your keyboard, press the Ctrl key. Then, select the buttons next to the other rows you want to select. e) Choose the Transfer Selection button. The function module has now finished and the export parameter ET_COMP_NAMES is displayed. f) To view the data for the parameter, choose the Details View/Edit button. Call Function Module BC402_SELECT_COMPONENTS Copy program BC402_DYS_CREATE_DATA or your own program ZBC402_##_CREATE_DATA and name it ZBC402_##_RTTC. Familiarize yourself with the program and how it works. Implement a call of the function module before the dynamic generation of the data object. Pass the table name that the user entered on the selection screen to the import parameter. 1. Copy the program and all its subcomponents. a) In the unnamed dropdown menu on the left of the screen, choose Program and specify the name of the program ZBC402_##_CREATE_DATA. b) Choose Display. c) Right-click ZBC402_##_CREATE_DATA and choose Copy.... d) In the Copy Program ZBC402_##_CREATE_DATA dialog box, in the Target program field, enter ZBC402_##_RTTC and choose Copy. e) In the Copy Program ZBC402_##_CREATE_DATA to ZBC402_##_RTTC dialog box, select all checkboxes and choose Copy. f) In the Create Object Directory Entry dialog box, in the Package field, enter ZBC402_## and choose Save. 2. Call the function module before the CREATE DATA statement. Create a suitably typed data object to import the data from the function module parameter ET_COMP_NAMES. Pass the contents of gv_tabname to the import parameter. React to exceptions with suitable error messages from message class BC402. a) See the source code excerpt from the model solution. Copy the Template Class Copy the template class CL_BC402_DYT_RTTC and name it ZCL_BC402_##_RTTC. Familiarize yourself with the signature of method create_table_type. 1. Copy the global class. a) In the unnamed dropdown menu on the left of the screen, choose Class/Interface and specify the name of the class CL_BC402_DYT_RTTC. b) Choose Display. c) Right-click CL_BC402_DYT_RTTC and choose Copy....
© Copyright. All rights reserved.
525
Unit 11: Dynamic Programming
d) In the Copy CL_BC402_DYT_RTTC dialog box, in the Copy to field, enter ZCL_BC402_##_RTTC and choose Copy. e) In the Create Object Directory Entry dialog box, in the Package field, enter ZBC402_## and choose Save. f) In the Methods tab, choose the Parameter button. 2. Analyze the create_table_type method signature. Which parameters are defined? How are they typed? Import parameter iv_tabname with generic type csequence, import parameter it_comp_names with type string_table, and return parameter ro_tabledescr, a reference to class cl_abap_tabledescr. Implement the create_table_type Method Use RTTI techniques to analyze the data type of the database table name contained in the import parameter. Use a suitable navigation method to create a list with the names and RTTI type description objects for all components in the structure. 1. Call a suitable method of class CL_ABAP_TYPEDESCR to generate a type description object for the data type. Create a reference variable with a suitable type for the return value (suggested name: lo_struct). Hint: For simplicity, assume that the data type is a structure type in the ABAP Dictionary and perform a direct down cast to the corresponding reference variable. a) Chose the Back to Methods button. b) In the Methods tab, double-click CREATE_TABLE_TYPE and choose the Display<>Change button. c) See the source code excerpt from the model solution. 2. Call the get_components method for the RTTI instance. Create a data object with a suitable type for the return value (suggested name is lt_comps). a) See the source code excerpt from the model solution. Create a Table Type Description Object with Only the Required Components Change the list of components so that it only contains the components listed in import parameter it_comp_names. Based on this list of components, create a new structure type, and then a new table type. 1. Implement a loop over the lt_comps component list. a) See the source code excerpt from the model solution. 2. Check whether the component name in each line is contained in import parameter it_comp_names.
526
© Copyright. All rights reserved.
Lesson: Creating Data Types, Data Objects, and Objects at Runtime
Hint: Use a statement such as FIND ... IN TABLE or READ TABLE ... TRANSPORTING NO FIELDS. a) See the source code excerpt from the model solution. 3. Remove the current line from lt_comps if the corresponding table name is not contained in import parameter it_comp_names. Hint: Use the abbreviated syntax for index access in loops here.
a) See the source code excerpt from the model solution. 4. To generate an RTTI type description object for a new structure type, call the CREATE method of class CL_ABAP_STRUCTDESCR. Pass the reduced component list to the method. Create a data object with a suitable type for the return parameter (suggested name: lo_struct_new). a) See the source code excerpt from the model solution. 5. To generate an RTTI type description object for a new table type, call the CREATE method of class CL_ABAP_TABLEDESCR. Pass the reference to the RTTI object for the new structure type. Leave all the optional parameters set to their default values. Transfer the result of the method call directly to return parameter ro_table_def of method create_table_type. a) See the source code excerpt from the model solution. Call an Internal Table at Runtime with Only the Required Components Go back to your executable program ZBC402_##_RTTC. Call method create_table_type to generate a table type according to the requirements of the user. Use the new data type when you generate the data object dynamically. Change the SELECT statement so that it reads only those fields from the database that are contained in the line type of the internal table. Hint: Method write_headers still outputs the headers for all the columns in the table. Either work without the headers completely or use method write_headers_by_data from class CL_BC402_DYS_RTTI_HEADERS. This method analyzes the actual line type of an internal table and outputs the column headers for it. 1. Call method create_table_type in the program directly after the call of function module BC402_SELECT_COMPONENTS. Pass the name of the database table and the list of components that the user selected to the method create_table_type. a) In transaction SE80, in the unnamed dropdown list on the left of the screen, choose Program. b) In the field underneath Program, enter the name ZBC402_##_RTTC, and choose Display.
© Copyright. All rights reserved.
527
Unit 11: Dynamic Programming
c) In the Object list, double-click the program name. d) See the source code excerpt from the model solution. 2. Change the type in the CREATE DATA statement. Use the TYPE HANDLE addition to use the newly generated table type. a) See the source code excerpt from the model solution. 3. Change the SELECT statement. Use the list of component names as a dynamic field list. Hint: Alternatively, use the INTO CORRESPONDING FIELDS OF TABLE addition.
4. Activate and test your program. a) Choose the Check button. b) Choose the Activate button. c) Choose the Direct Processing button. Source code excerpt from the model solution: Method create_table_type (Class CL_BC402_DYS_RTTC) METHOD create_table_type. DATA: lo_struct TYPE REF TO cl_abap_structdescr, lo_struct_new TYPE REF TO cl_abap_structdescr. DATA: lt_comps TYPE cl_abap_structdescr=>component_table. FIELD-SYMBOLS: LIKE LINE OF lt_comps. * get description of transparent table (=structure type) lo_struct ?= cl_abap_typedescr=>describe_by_name( iv_tabname ). * get list of components (including component types) lt_comps = lo_struct->get_components( ). LOOP AT lt_comps ASSIGNING . FIND -name IN TABLE it_comp_names. IF sy-subrc <> 0. DELETE lt_comps. ENDIF. ENDLOOP. * alternatve solution with read table * remove all components but the requested ones * LOOP AT lt_comps ASSIGNING . * READ TABLE it_comp_names * TRANSPORTING NO FIELDS * WITH TABLE KEY table_line = -name. * IF sy-subrc <> 0.
528
© Copyright. All rights reserved.
Lesson: Creating Data Types, Data Objects, and Objects at Runtime
* * * *
DELETE lt_comps . ENDIF. ENDLOOP.
* create new structure type with the remaining components lo_struct_new = cl_abap_structdescr=>create( p_components = lt_comps ). * create table type with this new structure type as line type ro_tabledescr = cl_abap_tabledescr=>create( p_line_type = lo_struct_new ). ENDMETHOD. Executable Program BC402_DYS_RTTC REPORT
bc402_dys_rttc MESSAGE-ID bc402.
DATA: gr_table
TYPE REF TO data.
DATA: gv_tabname TYPE string. DATA: gt_comp_names TYPE string_table, go_table TYPE REF TO cl_abap_tabledescr. FIELD-SYMBOLS: TYPE ANY TABLE. SELECTION-SCREEN COMMENT 1(80) text-sel. PARAMETERS pa_tab TYPE dd02l-tabname DEFAULT 'SPFLI'. PARAMETERS: pa_nol TYPE i DEFAULT '100'. START-OF-SELECTION. gv_tabname = pa_tab. CALL FUNCTION 'BC402_SELECT_COMPONENTS' EXPORTING iv_tabname = gv_tabname IMPORTING et_comp_names = gt_comp_names EXCEPTIONS type_not_found = 1 no_structure = 2 no_ddic_type = 3. CASE sy-subrc. WHEN 1. MESSAGE e050 WITH gv_tabname. WHEN 2. MESSAGE e051 WITH gv_tabname. WHEN 3. MESSAGE e052 WITH gv_tabname. ENDCASE. go_table = cl_bc402_dys_rttc=>create_table_type( iv_tabname = gv_tabname
© Copyright. All rights reserved.
529
Unit 11: Dynamic Programming
it_comp_names = gt_comp_names ). CREATE DATA gr_table TYPE HANDLE go_table. ASSIGN gr_table->* TO . TRY.
SELECT (gt_comp_names) FROM (gv_tabname) INTO TABLE UP TO pa_nol ROWS. CATCH cx_sy_dynamic_osql_error. MESSAGE e061. ENDTRY. CALL METHOD cl_bc402_dys_rtti_headers=>write_headers_by_data EXPORTING it_table = EXCEPTIONS no_structure = 1 no_ddic_type = 2 component_not_elem = 3. CASE sy-subrc. WHEN 1. MESSAGE e050 WITH gv_tabname. WHEN 2. MESSAGE e051 WITH gv_tabname. WHEN 3. MESSAGE e053 WITH gv_tabname. ENDCASE. cl_bc402_dys_gen_types=>write_any_table( ).
530
© Copyright. All rights reserved.
Lesson: Creating Data Types, Data Objects, and Objects at Runtime
LESSON SUMMARY You should now be able to: ●
Create objects at runtime
●
Create data objects at runtime
●
Create data types at runtime
© Copyright. All rights reserved.
531
Unit 11: Dynamic Programming
532
© Copyright. All rights reserved.
Unit 11 Learning Assessment
1. Field symbols are pointers that you can assign to data objects dynamically at runtime. Determine whether this statement is true or false. X
True
X
False
2. If a field symbol is assigned to a data object, all accesses you make to the field symbol are made directly to that data object. Determine whether this statement is true or false. X
True
X
False
3. What is the variant of the ASSIGN statement that provides access to structure components dynamically? Choose the correct answer. X
A ASSIGN COMPONENT ... TO STRUCTURE ...
X
B ASSIGN COMPONENT ... OF STRUCTURE ...
X
C ASSIGN COMPONENT ... WITH STRUCTURE ...
X
D ASSIGN COMPONENT ... IN STRUCTURE ...
4. When you assign values between two reference variables with different types, you perform what is called a cast assignment. Determine whether this statement is true or false. X
True
X
False
© Copyright. All rights reserved.
533
Unit 11: Learning Assessment
5. Which of the following classes can be instantiated and used to describe specific types? Choose the correct answers. X
A CL_ABAP_ELEMDESCR
X
B CL_ABAP_INTFDESCR
X
C CL_ABAP_STRUCTDESCR
X
D CL_ABAP_RTTI
6. The description classes for object types provide navigation methods for determining the details of a used type. Determine whether this statement is true or false. X
True
X
False
7. Class CL_ABAP_CLASSDESCR contains public attributes that are typed as internal tables. Determine whether this statement is true or false. X
True
X
False
8. To generate objects at runtime, the static type of the reference variable must be compatible with the class. Determine whether this statement is true or false. X
True
X
False
9. The ___________ statement creates a data object dynamically at runtime. Choose the correct answer.
534
X
A CREATE OBJECT
X
B CREATE DATA
X
C ASSIGN
X
D GET REFERENCE OF
© Copyright. All rights reserved.
Unit 11: Learning Assessment
10. With the HANDLE addition, the CREATE DATA statement creates a data object whose data type is described by an RTTI type object. Determine whether this statement is true or false. X
True
X
False
© Copyright. All rights reserved.
535
Unit 11 Learning Assessment - Answers
1. Field symbols are pointers that you can assign to data objects dynamically at runtime. Determine whether this statement is true or false. X
True
X
False
2. If a field symbol is assigned to a data object, all accesses you make to the field symbol are made directly to that data object. Determine whether this statement is true or false. X
True
X
False
3. What is the variant of the ASSIGN statement that provides access to structure components dynamically? Choose the correct answer. X
A ASSIGN COMPONENT ... TO STRUCTURE ...
X
B ASSIGN COMPONENT ... OF STRUCTURE ...
X
C ASSIGN COMPONENT ... WITH STRUCTURE ...
X
D ASSIGN COMPONENT ... IN STRUCTURE ...
4. When you assign values between two reference variables with different types, you perform what is called a cast assignment. Determine whether this statement is true or false.
536
X
True
X
False
© Copyright. All rights reserved.
Unit 11: Learning Assessment - Answers
5. Which of the following classes can be instantiated and used to describe specific types? Choose the correct answers. X
A CL_ABAP_ELEMDESCR
X
B CL_ABAP_INTFDESCR
X
C CL_ABAP_STRUCTDESCR
X
D CL_ABAP_RTTI
6. The description classes for object types provide navigation methods for determining the details of a used type. Determine whether this statement is true or false. X
True
X
False
7. Class CL_ABAP_CLASSDESCR contains public attributes that are typed as internal tables. Determine whether this statement is true or false. X
True
X
False
8. To generate objects at runtime, the static type of the reference variable must be compatible with the class. Determine whether this statement is true or false. X
True
X
False
9. The ___________ statement creates a data object dynamically at runtime. Choose the correct answer. X
A CREATE OBJECT
X
B CREATE DATA
X
C ASSIGN
X
D GET REFERENCE OF
© Copyright. All rights reserved.
537
Unit 11: Learning Assessment - Answers
10. With the HANDLE addition, the CREATE DATA statement creates a data object whose data type is described by an RTTI type object. Determine whether this statement is true or false.
538
X
True
X
False
© Copyright. All rights reserved.