BC401 ABAP Objects . . PARTICIPANT HANDBOOK INSTRUCTOR-LED TRAINING . Course Version: 16 Course Duration: 5 Day(s) e-book Duration: 36 Hours 40 Minutes Material Number: 50134934 SAP Copyrights and Trademarks © 2016 SAP SE or an SAP affiliate company. 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 or an SAP affiliate company. SAP and other SAP products and services mentioned herein as well as their respective logos are trademarks or registered trademarks of SAP SE (or an SAP affiliate company) in Germany and other countries. Please see http://global12.sap.com/corporate-en/legal/ copyright/index.epx for additional trademark information and notices. Some software products marketed by SAP SE and its distributors contain proprietary software components of other software vendors. National product specifications may vary. These materials are provided by SAP SE or an SAP affiliate company for informational purposes only, without representation or warranty of any kind, and SAP SE or its affiliated companies shall not be liable for errors or omissions with respect to the materials. The only warranties for SAP SE or SAP affiliate company 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. In particular, SAP SE or its affiliated companies have no obligation to pursue any course of business outlined in this document or any related presentation, or to develop or release any functionality mentioned therein. This document, or any related presentation, and SAP SE’s or its affiliated companies’ strategy and possible future developments, products, and/or platform directions and functionality are all subject to change and may be changed by SAP SE or its affiliated companies at any time for any reason without notice. The information in this document is not a commitment, promise, or legal obligation to deliver any material, code, or functionality. All forward-looking statements are subject to various risks and uncertainties that could cause actual results to differ materially from expectations. Readers are cautioned not to place undue reliance on these forward-looking statements, which speak only as of their dates, and they should not be relied upon in making purchasing decisions. 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. iii iv © Copyright. All rights reserved. Contents ix Course Overview 1 Unit 1: 2 14 Lesson: Explaining the Object-Oriented Programming Model Lesson: Analyzing and Designing with Unified Modeling Language (UML) Exercise 1: Create UML Diagrams 27 37 Unit 2: 39 53 60 67 71 77 83 87 95 99 115 Fundamental Object-Oriented Syntax 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: 116 125 135 139 144 149 155 159 173 Introduction to Object-Oriented Programming 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 174 179 189 193 200 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 203 Exercise 13: Integrate Class Models Using Interfaces © Copyright. All rights reserved. v 223 Unit 5: 224 Lesson: Implementing Events in Local Classes 233 246 247 Exercise 14: Implement Events in Local Classes Lesson: Implementing Events in Local Interfaces Exercise 15: Implement Handling of Interface Events 261 Unit 6: 262 273 283 287 298 307 341 Unit 7: 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) Unit 8: 342 349 Global Classes in ABAP Development Tools Lesson: Developing Eclipse-Based ABAP Programs Exercise 20: Edit a Global Class and an Executable Program in ABAP Development Tools (ADT) Exercise 21: Use Refactoring Functions in ADT 363 373 Object-Oriented Repository Objects Lesson: Creating Global Classes Exercise 16: Implement a Global Class Lesson: Defining and Implementing Global Interfaces Exercise 17: Import and Implement a Global Interface Lesson: Implementing Inheritance in Global Classes 308 315 321 330 Unit 9: Class-Based Exceptions 374 Lesson: Explaining Class-Based Exceptions 380 389 403 411 Lesson: Defining and Raising Exceptions Exercise 22: Implement Class-Based Exceptions Lesson: Implementing Advanced Exception Handling Techniques Exercise 23: Map Exceptions to Each Other 429 Unit 10: 430 437 451 453 463 467 476 479 490 vi Object-Oriented Events Unit Testing Lesson: Unit Testing with ABAP Unit Exercise 24: Execute an ABAP Unit Test Unit 11: Object-Oriented Design Patterns Lesson: Implementing Advanced Object-Oriented Techniques Lesson: Implementing the Singleton Pattern Exercise 25: Implement the Singleton Pattern Lesson: Implementing Factory Classes Using Friendship Exercise 26: Implement a Factory Class Using Friendship Lesson: Implementing Persistent Objects © Copyright. All rights reserved. 503 Unit 12: 504 Runtime Type Services Lesson: Using Runtime Type Identification (RTTI) 511 519 520 525 529 Exercise 27: Describe Object Type Properties at Runtime Unit 13: Creation of a Comprehensive Object-Oriented Application Lesson: Developing a Comprehensive Object-Oriented Application Exercise 28: Create an UML Class Diagram Exercise 29: Develop a Comprehensive Object-Oriented Application © Copyright. All rights reserved. vii viii © 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. ix x © 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 14 27 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 2 © Copyright. All rights reserved. Lesson: Explaining the Object-Oriented Programming Model As you can see from the figure, History of Selected Programming Languages, object-oriented programming (such as the Simula 67 programming language), and the logical and procedural programming models (as used in languages such as C and Pascal), were developed at about the 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, such as COBOL and Pascal. ABAP was then extended to form ABAP Objects. Therefore, ABAP Objects unite 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. 4 © Copyright. All rights reserved. Lesson: Explaining the Object-Oriented Programming Model 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 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. © Copyright. All rights reserved. 5 Unit 1: Introduction to Object-Oriented Programming 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. 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. 6 © Copyright. All rights reserved. Lesson: Explaining the Object-Oriented Programming Model 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. 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. © Copyright. All rights reserved. 7 Unit 1: Introduction to Object-Oriented Programming 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. ● 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. 8 © Copyright. All rights reserved. Lesson: Explaining the Object-Oriented Programming Model 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, such as 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 between ABAP Objects and other object-oriented languages is 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. © Copyright. All rights reserved. 9 Unit 1: Introduction to Object-Oriented Programming 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: It is advisable to avoid obsolete statements in the purely procedural environment, because it creates safer and more flexible source code. However, 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. 10 © Copyright. All rights reserved. Lesson: Explaining the Object-Oriented Programming Model 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. © Copyright. All rights reserved. 11 Unit 1: Introduction to Object-Oriented Programming 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 12 ● Improved software structure and consistency in the development process ● Reduced maintenance effort and less susceptibility to errors © Copyright. All rights reserved. Lesson: Explaining the Object-Oriented Programming Model ● Better integration of the customer or user into the analysis, design, and maintenance process ● 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: ● Describe the differences between the procedural and object-oriented programming models © Copyright. All rights reserved. 13 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: 14 ● Classify objects ● Model in UML © Copyright. All rights reserved. Lesson: Analyzing and Designing with Unified Modeling Language (UML) Classification of Objects Figure 15: Classifying Objects 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 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. © Copyright. All rights reserved. 15 Unit 1: Introduction to Object-Oriented Programming 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. 16 © 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 © Copyright. All rights reserved. 17 Unit 1: Introduction to Object-Oriented Programming 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. 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. 18 © Copyright. All rights reserved. Lesson: Analyzing and Designing with Unified Modeling Language (UML) Example of a Class Diagram Figure 19: An Example of a Class Diagram 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. © Copyright. All rights reserved. 19 Unit 1: Introduction to Object-Oriented Programming 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 the other hand, the cardinality of any number would allow for a more general definition of a customer. Characteristics of association are as follows: 20 ● 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. © Copyright. All rights reserved. Lesson: Analyzing and Designing with Unified Modeling Language (UML) ● 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 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. © Copyright. All rights reserved. 21 Unit 1: Introduction to Object-Oriented Programming 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. 22 © Copyright. All rights reserved. Lesson: Analyzing and Designing with Unified Modeling Language (UML) Aggregation and composition appear as a line between two classes. They are labeled 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 that the contained object cannot exist without the aggregation (for example, a car reservation cannot exist without the 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 that 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. © Copyright. All rights reserved. 23 Unit 1: Introduction to Object-Oriented Programming 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. Explain the structure of the exercise on object diagrams. There are eight possible object diagrams for the class diagram. The participants must determine the right and wrong object diagrams in a multiple choice assessment. The sequence diagrams complete the unit on modeling. You do not need to mention the sequence diagrams for the rest of the course because there is no exercise for this concept. 24 © Copyright. All rights reserved. Lesson: Analyzing and Designing with Unified Modeling Language (UML) 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 ● 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. © Copyright. All rights reserved. 25 Unit 1: Introduction to Object-Oriented Programming 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. 26 © 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 select the corresponding checkbox to indicate your answer. © Copyright. All rights reserved. 27 Unit 1: Introduction to Object-Oriented Programming Figure 29: Possible Object Diagrams (1) Figure 30: Possible Object Diagrams (2) 28 © 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) 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. 29 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 select the corresponding checkbox to indicate your answer. Figure 29: Possible Object Diagrams (1) 30 © 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. 31 Unit 1: Introduction to Object-Oriented Programming LESSON SUMMARY You should now be able to: 32 ● 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. 33 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. 34 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. 35 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. 36 X True X False © Copyright. All rights reserved. UNIT 2 Fundamental Object-Oriented Syntax Lesson 1 Creating Local Classes Exercise 2: Create Local Classes 39 53 Lesson 2 Creating Objects Exercise 3: Create Objects 60 67 Lesson 3 Accessing Methods and Attributes Exercise 4: Call Methods 71 77 Lesson 4 Implementing Constructors in Local Classes Exercise 5: Create and Use Constructors 83 87 Lesson 5 Implementing Class Constructors in Local Classes Exercise 6: Create and Use Static Constructors 95 99 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. 37 Unit 2: Fundamental Object-Oriented Syntax 38 ● 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 © Copyright. All rights reserved. 39 Unit 2: Fundamental Object-Oriented Syntax methods and events, from outside a class. However, you cannot access private components, for example data types and attributes, from outside a class. 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: 40 ● 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. © Copyright. All rights reserved. Lesson: Creating Local 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 attributes are as follows: ● 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 © Copyright. All rights reserved. 41 Unit 2: Fundamental Object-Oriented Syntax 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. 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. 42 © Copyright. All rights reserved. Lesson: Creating Local Classes 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. Therefore, use public attributes sparingly, or avoid making incompatible changes to public components altogether. © Copyright. All rights reserved. 43 Unit 2: Fundamental Object-Oriented Syntax 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 rsky because the user may forget to supply the attributes or specify inconsistent attributes. To solve 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. 44 © Copyright. All rights reserved. Lesson: Creating Local Classes 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”. © Copyright. All rights reserved. 45 Unit 2: Fundamental Object-Oriented Syntax Instance Attributes and Static Attributes in the Program Context Figure 38: Instance Attributes and Static Attributes in the Program Context 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. 46 © Copyright. All rights reserved. Lesson: Creating Local Classes 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 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. © Copyright. All rights reserved. 47 Unit 2: Fundamental Object-Oriented Syntax 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. 48 © 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 access private methods directly 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. 49 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. 50 © 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. 51 Unit 2: Fundamental Object-Oriented Syntax 52 © 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. In the exercises for this course, when the input values include ##, replace ## with your group number. Solution: SAPBC401_BAS_S1. Create a Program 1. Create an executable program, ZBC401_##_MAIN, without a TOP include. 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 and Description Data type Attribute Type MV_NAME STRING Private instance attribute SAPLANE-PLANETYPE Private instance attribute (name of airplane) MV_PLANETYPE (type of airplane) GV_N_O_AIRPLANES I Private static attribute (instance counter) 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. 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. © Copyright. All rights reserved. 53 Unit 2: Fundamental Object-Oriented Syntax 6. Implement the public instance method DISPLAY_ATTRIBUTES so that the values of the two instance attributes are output as an ABAP list. You can also output icons from the type group ICON. 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 whether you want to omit the counter for now, or 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<number> 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. 54 © 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. In the exercises for this course, when the input values include ##, replace ## with your group number. Solution: SAPBC401_BAS_S1. Create a Program 1. Create an executable program, ZBC401_##_MAIN, without a TOP include. 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 requestdialog box, choose Own Requests. f) Choose a request and choose Continue. g) Under Object Name, choose the package name and, from the context menu, choose Create → Program. 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 Changedialog box, enter a title for the program. Leave all other default settings and choose Save. j) In the Create Object Directory Entrydialog box, assign the program to your own package, ZBC401_##, and choose Save. k) In the Prompt for transportable Workbench requestdialog box, assign the program to your own transport request and choose Continue. The ABAP Editor: Change Report ZBC401_##_MAINscreen 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. © Copyright. All rights reserved. 55 Unit 2: Fundamental Object-Oriented Syntax a) See the source code extract from the model solution. 2. Define the following attributes: Table 3: Attributes Attribute Name and Description Data type Attribute Type MV_NAME STRING Private instance attribute SAPLANE-PLANETYPE Private instance attribute (name of airplane) MV_PLANETYPE (type of airplane) GV_N_O_AIRPLANES I Private static attribute (instance counter) 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 so 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. 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. 56 © Copyright. All rights reserved. Lesson: Creating Local Classes Note: So far, your class does not have a mechanism for ensuring that the instance counter increases each time an object is created. Decide whether you want to omit the counter for now, or 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<number> 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 Processingbutton. 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. DATA: mv_name TYPE string, mv_planetype TYPE saplane-planetype. CLASS-DATA: © Copyright. All rights reserved. 57 Unit 2: Fundamental Object-Oriented Syntax 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 58 © 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. 59 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. 60 © Copyright. All rights reserved. Lesson: Creating Objects 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 runtime instances of classes. 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. © Copyright. All rights reserved. 61 Unit 2: Fundamental Object-Oriented Syntax 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. Reference Semantics of Object References Figure 47: Reference Semantics of Object References Object reference variables can be assigned to each other. 62 © Copyright. All rights reserved. Lesson: Creating Objects 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. 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. © Copyright. All rights reserved. 63 Unit 2: Fundamental Object-Oriented Syntax 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. Example of Aggregation Figure 50: Example of Aggregation 64 © Copyright. All rights reserved. Lesson: Creating Objects 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. © Copyright. All rights reserved. 65 Unit 2: Fundamental Object-Oriented Syntax 66 © 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. 67 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. 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. 68 © Copyright. All rights reserved. Lesson: Creating Objects 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. 69 Unit 2: Fundamental Object-Oriented Syntax LESSON SUMMARY You should now be able to: ● 70 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 © Copyright. All rights reserved. 71 Unit 2: Fundamental Object-Oriented Syntax This section explains the use of classes and their instances, from the static connections of various instances to their practical effects. 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 NetWeaver Application Server (SAP NetWeaver 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. 72 © Copyright. All rights reserved. Lesson: Accessing Methods and Attributes Static Method Calls Figure 53: Calling Static Methods – Syntax Use CALL METHOD 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. 73 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. 74 © 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. © Copyright. All rights reserved. 75 Unit 2: Fundamental Object-Oriented Syntax Access to Public Attributes Figure 56: Accessing Public Attributes 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. 76 © 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. Call 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. Add 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. 77 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. Call 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 might 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. Add 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. 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. 78 © Copyright. All rights reserved. Lesson: Accessing Methods and Attributes 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 Processingbutton. 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: gv_n_o_airplanes = gv_n_o_airplanes + 1. © Copyright. All rights reserved. 79 Unit 2: Fundamental Object-Oriented Syntax 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. * * * * * * 80 long syntax for functional call: CALL METHOD lcl_airplane=>get_n_o_airplanes RECEIVING rv_count = gv_count. a little bit shorter: © Copyright. All rights reserved. Lesson: Accessing Methods and Attributes * 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. 81 Unit 2: Fundamental Object-Oriented Syntax LESSON SUMMARY You should now be able to: 82 ● 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. 83 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: ● 84 You must allocate resources. © Copyright. All rights reserved. Lesson: Implementing Constructors in Local Classes ● You must initialize attributes that cannot be covered by the VALUE addition to the DATA statement. ● You modify static attributes. ● You must inform other objects about the object creation. © Copyright. All rights reserved. 85 Unit 2: Fundamental Object-Oriented Syntax 86 © 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 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. 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. © Copyright. All rights reserved. 87 Unit 2: Fundamental Object-Oriented Syntax 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 nonexisting airplane type to see how the exception handling works. 88 © 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 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. 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. 89 Unit 2: Fundamental Object-Oriented Syntax 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 nonexisting 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 * *-------------------------------------------------* CLASS lcl_airplane DEFINITION. PUBLIC SECTION. METHODS: constructor 90 © Copyright. All rights reserved. Lesson: Implementing Constructors in Local Classes 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. 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, / 'Weight:'(003), AT c_pos_1 mv_weight © Copyright. All rights reserved. 91 Unit 2: Fundamental Object-Oriented Syntax LEFT-JUSTIFIED, / 'Tank capacity:'(004), LEFT-JUSTIFIED. ENDMETHOD. 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. IF sy-subrc = 0. APPEND go_airplane TO gt_airplanes. ENDIF. LOOP AT gt_airplanes INTO go_airplane. go_airplane->display_attributes( ). 92 © Copyright. All rights reserved. Lesson: Implementing Constructors in Local Classes ENDLOOP. gv_count = lcl_airplane=>get_n_o_airplanes( ). SKIP 2. WRITE: / 'Number of airplanes'(ca1), gv_count. © Copyright. All rights reserved. 93 Unit 2: Fundamental Object-Oriented Syntax LESSON SUMMARY You should now be able to: ● 94 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 © Copyright. All rights reserved. 95 Unit 2: Fundamental Object-Oriented Syntax 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: ● 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. 96 © Copyright. All rights reserved. Lesson: Implementing Class Constructors in Local Classes 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. © Copyright. All rights reserved. 97 Unit 2: Fundamental Object-Oriented Syntax 98 © 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? 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. © Copyright. All rights reserved. 99 Unit 2: Fundamental Object-Oriented Syntax 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? 100 © 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. 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. © Copyright. All rights reserved. 101 Unit 2: Fundamental Object-Oriented Syntax 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. 4. Observe the execution of the program in the ABAP Debugger. 5. Which alternative solutions could be used to solve the tasks? 102 © Copyright. All rights reserved. Lesson: Implementing Class Constructors in Local Classes 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. CLASS-METHODS: get_technical_attributes IMPORTING © Copyright. All rights reserved. 103 Unit 2: Fundamental Object-Oriented Syntax 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. 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), 104 © Copyright. All rights reserved. Lesson: Implementing Class Constructors in Local Classes 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 wrong_planetype = 1. IF sy-subrc = 0. APPEND go_airplane TO gt_airplanes. ENDIF. © Copyright. All rights reserved. 105 Unit 2: Fundamental Object-Oriented Syntax 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. 106 © 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. 107 Unit 2: Fundamental Object-Oriented Syntax 108 © 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. 109 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. 110 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. 111 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. 112 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. 113 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. 114 X True X False © Copyright. All rights reserved. UNIT 3 Inheritance and Casting Lesson 1 Implementing Inheritance Exercise 7: Implement Inheritance 116 125 Lesson 2 Implementing Upcasts Using Inheritance Exercise 8: Implement Upcasts 135 139 Lesson 3 Implementing Polymorphism Using Inheritance Exercise 9: Implement Polymorphism Using Inheritance 144 149 Lesson 4 Implementing Downcasts Using Inheritance Exercise 10: Implement Downcasts 155 159 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. 115 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 116 © Copyright. All rights reserved. Lesson: Implementing Inheritance 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 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 provide 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. 117 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. 118 © 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. © Copyright. All rights reserved. 119 Unit 3: Inheritance and Casting Preserving Semantics During Redefinition Figure 65: Preserving Semantics During Redefinition 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 120 © Copyright. All rights reserved. Lesson: Implementing Inheritance 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. 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 © Copyright. All rights reserved. 121 Unit 3: Inheritance and Casting 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 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. 122 © Copyright. All rights reserved. Lesson: Implementing Inheritance 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 address 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 The following is a summary of static components and inheritance: ● A class that defines a public or protected static attribute shares this attribute with all its subclasses. ● Static methods cannot be redefined. ● 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. © Copyright. All rights reserved. 123 Unit 3: Inheritance and Casting ● 124 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. If 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. 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 that 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. 1. The class must have a private instance attribute, MV_CARGO , with the same type as the table field SCPLANE-CARGOMAX. © Copyright. All rights reserved. 125 Unit 3: Inheritance and Casting 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. 126 © 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. Make sure that 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. © Copyright. All rights reserved. 127 Unit 3: Inheritance and Casting 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. 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. 128 © Copyright. All rights reserved. Lesson: Implementing Inheritance 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 EXCEPTIONS wrong_planetype. © Copyright. All rights reserved. 129 Unit 3: Inheritance and Casting 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. READ TABLE gt_planetypes INTO ls_planetype WITH TABLE KEY planetype = iv_type TRANSPORTING weight tankcap. 130 © Copyright. All rights reserved. Lesson: Implementing Inheritance 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( ). WRITE: / 'Max Cargo:'(005), AT c_pos_1 mv_cargo LEFT-JUSTIFIED. ULINE. © Copyright. All rights reserved. 131 Unit 3: Inheritance and Casting ENDMETHOD. ENDCLASS. "display_attributes "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: go_airplane go_cargo go_passenger gt_airplanes 132 TYPE TYPE TYPE TYPE REF TO lcl_airplane, REF TO lcl_cargo_plane, REF TO lcl_passenger_plane, TABLE OF REF TO lcl_airplane, © Copyright. All rights reserved. Lesson: Implementing Inheritance gv_count TYPE 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. 133 Unit 3: Inheritance and Casting LESSON SUMMARY You should now be able to: 134 ● 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: Upcast (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. © Copyright. All rights reserved. 135 Unit 3: Inheritance and Casting The user can address only those methods and attributes from the subclass instance that they can from the superclass instance. 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> 136 © Copyright. All rights reserved. Lesson: Implementing Upcasts Using Inheritance 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. © Copyright. All rights reserved. 137 Unit 3: Inheritance and Casting 138 © 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. In the exercises for this course, when the input values include ##, replace ## with your group number. 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 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 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. 139 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. In the exercises for this course, when the input values include ##, replace ## with your group number. 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 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 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. 140 © 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. 141 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. 142 © 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. 143 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 144 © Copyright. All rights reserved. Lesson: Implementing Polymorphism Using Inheritance 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 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. © Copyright. All rights reserved. 145 Unit 3: Inheritance and Casting Up-Cast and Generic Access in the Application – Example Figure 74: Up-Cast and Generic Access in the Application – Example 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. 146 © Copyright. All rights reserved. Lesson: Implementing Polymorphism Using Inheritance Polymorphism Figure 75: Polymorphism – Generic Access Using the Superclass Reference The implementation to be executed when DISPLAY_ATTRIBUTES is called depends 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 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. © Copyright. All rights reserved. 147 Unit 3: Inheritance and Casting 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. 148 © 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. In the exercises for this course, when the input values include ##, replace ## with your group number. Template: SAPBC401_INH_T3. Solution: SAPBC401_INH_S3 . Define a Local Class Define a local class for airlines. 1. Complete your program ZBC401_##_MAIN or copy the template program. If you copy the template program, 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 storereferences 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 of 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. 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. © Copyright. All rights reserved. 149 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. In the exercises for this course, when the input values include ##, replace ## with your group number. Template: SAPBC401_INH_T3. Solution: SAPBC401_INH_S3 . Define a Local Class Define a local class for airlines. 1. Complete your program ZBC401_##_MAIN or copy the template program. If you copy the template program, 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 storereferences 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. 1. Remove all of 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. 150 © Copyright. All rights reserved. Lesson: Implementing Polymorphism Using Inheritance 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 *------------------------------------------------* * CLASS lcl_passenger_plane IMPLEMENTATION *------------------------------------------------* CLASS lcl_passenger_plane IMPLEMENTATION. © Copyright. All rights reserved. 151 Unit 3: Inheritance and Casting ... 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, go_cargo TYPE REF TO lcl_cargo_plane, go_passenger TYPE REF TO lcl_passenger_plane, gv_count TYPE i. 152 © Copyright. All rights reserved. Lesson: Implementing Polymorphism Using Inheritance 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( ). © Copyright. All rights reserved. 153 Unit 3: Inheritance and Casting LESSON SUMMARY You should now be able to: 154 ● Explain polymorphism ● Implement polymorphism using inheritance © Copyright. All rights reserved. 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: Downcast (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. © Copyright. All rights reserved. 155 Unit 3: Inheritance and Casting To assign a superclass reference to a subclass reference, you must use the downcast 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, Downcast (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 Downcast Assignments Figure 78: Specific Access After Downcast Assignments Downcast 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. 156 © Copyright. All rights reserved. Lesson: Implementing Downcasts Using Inheritance 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 downcast 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. © Copyright. All rights reserved. 157 Unit 3: Inheritance and Casting 158 © 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 downcast technique to identify cargo planes. For those airplanes for which the downcast 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. 159 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 downcast technique to identify cargo planes. For those airplanes for which the downcast 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 IMPORTING iv_name TYPE string iv_planetype TYPE saplane-planetype iv_cargo TYPE s_plan_car 160 © Copyright. All rights reserved. Lesson: Implementing Downcasts Using Inheritance 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, add_airplane IMPORTING io_plane TYPE REF TO lcl_airplane. © Copyright. All rights reserved. 161 Unit 3: Inheritance and Casting 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. IF rv_max_cargo < lo_cargo->get_cargo( ). rv_max_cargo = lo_cargo->get_cargo( ). ENDIF. 162 © Copyright. All rights reserved. Lesson: Implementing Downcasts Using Inheritance * 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 163 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. 164 © 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. 165 Unit 3: Inheritance and Casting LESSON SUMMARY You should now be able to: 166 ● 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. 167 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 downcast assignment operator? Choose the correct answer. 168 X A = X B <> X C ?= X D =? © Copyright. All rights reserved. Unit 3: Learning Assessment 8. Suppose that 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 9. 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. 169 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. 170 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 downcast assignment operator? Choose the correct answer. X A = X B <> X C ?= X D =? © Copyright. All rights reserved. 171 Unit 3: Learning Assessment - Answers 8. Suppose that 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 9. What are the advantages of correctly using class hierarchies? Choose the correct answers. 172 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 174 179 Lesson 2 Implementing Polymorphism Using Interfaces Exercise 12: Implement Polymorphism Using Interfaces 189 193 Lesson 3 Integrating Class Models Using Interfaces Exercise 13: Integrate Class Models Using Interfaces 200 203 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. 173 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. 174 © Copyright. All rights reserved. Lesson: Defining and Implementing Local Interfaces Interfaces can be seen as superclasses that cannot be instantiated, do not contain 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 Protocol 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. 175 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 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 176 © Copyright. All rights reserved. Lesson: Defining and Implementing Local Interfaces 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: ● 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 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. © Copyright. All rights reserved. 177 Unit 4: Interfaces and Casting Figure 87: Simplifying Access to Interface Components with Alias Names To simplify access to interface components, you can use alias names. These alias names can appear in the definition part of a class. 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. 178 © 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. In the exercises for this course, when the input values include ##, replace ## with your group number. 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 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). 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. 179 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 to later offer generic access options to potential clients in the travel agency example. 1. Create a new INCLUDE (recommended name: ZBC401_##_AGENCY) and define an interface LIF_PARTNER in the new INCLUDE. 2. Check the entire program for syntactical correctness and activate it. 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. 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. 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. 180 © Copyright. All rights reserved. Lesson: Defining and Implementing Local Interfaces 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. 181 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. In the exercises for this course, when the input values include ##, replace ## with your group number. 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 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). 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. a) See the source text excerpt from the model solution. 182 © Copyright. All rights reserved. Lesson: Defining and Implementing Local Interfaces 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 to later offer generic access options to potential clients in the travel agency example. 1. Create a new INCLUDE (recommended name: ZBC401_##_AGENCY) and define an interface LIF_PARTNER in the new INCLUDE. a) See the source text excerpt from the model solution. 2. Check the entire program for syntactical correctness and activate it. 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. 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. 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. © Copyright. All rights reserved. 183 Unit 4: Interfaces and Casting 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. IF sy-subrc = 0. go_carrier->add_airplane( go_passenger ). ENDIF. 184 © Copyright. All rights reserved. Lesson: Defining and Implementing Local Interfaces ***** 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 *--------------------------------------------------* CLASS lcl_cargo_plane IMPLEMENTATION. ... © Copyright. All rights reserved. 185 Unit 4: Interfaces and Casting 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. SKIP 2. WRITE: icon_flight AS ICON, mv_name. ULINE. 186 © Copyright. All rights reserved. Lesson: Defining and Implementing Local Interfaces 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 187 Unit 4: Interfaces and Casting LESSON SUMMARY You should now be able to: 188 ● 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 88: Upcast 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 upcast to copy a reference to the interface reference variable to perform polymorphism with interfaces. © Copyright. All rights reserved. 189 Unit 4: Interfaces and Casting 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 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 upcast. 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 89: Row Type of the Internal Table in the Application Example A typical area of use for upcast 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. 190 © Copyright. All rights reserved. Lesson: Implementing Polymorphism Using Interfaces 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. Generic Access Using the Interface Reference Figure 90: 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. 191 Unit 4: Interfaces and Casting 192 © 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. In the exercises for this course, when the input values include ##, replace ## with your group number. 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 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. 1. In the main program, define a suitably typed reference variable for your new travel agency class. © Copyright. All rights reserved. 193 Unit 4: Interfaces and Casting 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. 194 © 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. In the exercises for this course, when the input values include ##, replace ## with your group number. 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 or copy the template program with all its INCLUDES. a) Carry out this step as usual. 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. 195 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 *---------------------------------------------------* CLASS lcl_travel_agency IMPLEMENTATION. 196 © Copyright. All rights reserved. Lesson: Implementing Polymorphism Using Interfaces 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'. ***** Insert carrier into business partner list of ***** travel agency © Copyright. All rights reserved. 197 Unit 4: Interfaces and Casting 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( ). 198 © 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. 199 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 91: Down-Cast Assignment and Exception Handling in the Application Example 200 © Copyright. All rights reserved. Lesson: Integrating Class Models Using Interfaces 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 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. 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 the 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 then invalid 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. Submodel Integration Using Interfaces Submodels can be integrated with the help of interfaces. ● The steps to integrate a submodel using interfaces are as follows: 1. Create classes of the submodel. 2. Include given interface into server class of submodel. (Protocol is defined by client.) © Copyright. All rights reserved. 201 Unit 4: Interfaces and Casting 3. Create instances of server class and refer to them with interface reference. 202 © 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 Solutions: ● 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 reference pointers for LCL_RENTAL, LCL_VEHICLE, LCL_TRUCK AND LCL_BUS, and create an instance of LCL_RENTAL and a number of instances of the truck and bus classes. Add all of 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. © Copyright. All rights reserved. 203 Unit 4: Interfaces and Casting 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. 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? 204 © 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 Solutions: ● 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, enter BC401, and 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 dialog box displays. d) In the Copy Program dialog, in the Target Program field, enter ZBC401_##_RENTAL. Choose Copy. The Create Object Directory Entrydialog box displays. © Copyright. All rights reserved. 205 Unit 4: Interfaces and Casting e) In the Create Object Directory Entrydialog box, enter your package name and choose Save. The Prompt for transportable Workbench requestdialog box displays. f) In the Prompt for transportable Workbench requestdialog box, enter the request name supplied by your instructor. Choose Continue. g) Make the copied Include part of your own program. 2. In your main program, add reference pointers for LCL_RENTAL, LCL_VEHICLE, LCL_TRUCK AND LCL_BUS, and create an instance of LCL_RENTAL and a number of instances of the truck and bus classes. Add all of 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. 206 © 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 Processingbutton. 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 bus ****************************************** CREATE OBJECT go_bus EXPORTING iv_make = 'Mercedes' iv_passengers = 80. © Copyright. All rights reserved. 207 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: 208 © 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 209 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. 210 © 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 211 Unit 4: Interfaces and Casting Implementation of Interface Hierarchies Figure 92: 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. 212 © Copyright. All rights reserved. Lesson: Integrating Class Models Using Interfaces Compound Interface in Unified Modeling Language (UML) Notation Figure 93: 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. © Copyright. All rights reserved. 213 Unit 4: Interfaces and Casting Definition and Implementation of Compound Interfaces – Syntax Figure 94: Definition and Implementation of Compound Interfaces – Syntax 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. 214 © Copyright. All rights reserved. Lesson: Integrating Class Models Using Interfaces Addressing Components in Compound Interfaces – Syntax Figure 95: 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 96: 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. © Copyright. All rights reserved. 215 Unit 4: Interfaces and Casting 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. 216 © Copyright. All rights reserved. Lesson: Integrating Class Models Using Interfaces LESSON SUMMARY You should now be able to: ● Implement downcasts with interfaces ● Integrate different submodels using interfaces ● Create and use interface hierarchies © Copyright. All rights reserved. 217 Unit 4: Interfaces and Casting 218 © 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. 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 © Copyright. All rights reserved. 219 Unit 4: Learning Assessment 5. Which of the following strongly resembles inheritance? Choose the correct answer. X A Interface X B Class X C Method 6. Interfaces can include other interfaces. Determine whether this statement is true or false. 220 X True X False © Copyright. All rights reserved. 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. 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 © Copyright. All rights reserved. 221 Unit 4: Learning Assessment - Answers 5. Which of the following strongly resembles inheritance? Choose the correct answer. X A Interface X B Class X C Method 6. Interfaces can include other interfaces. Determine whether this statement is true or false. 222 X True X False © Copyright. All rights reserved. UNIT 5 Object-Oriented Events Lesson 1 Implementing Events in Local Classes Exercise 14: Implement Events in Local Classes 224 233 Lesson 2 Implementing Events in Local Interfaces Exercise 15: Implement Handling of Interface Events 246 247 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. 223 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: 224 ● Implement event-controlled method calls ● Trigger and handle events ● Register for events ● Explain visibility sections in event handling © Copyright. All rights reserved. Lesson: Implementing Events in Local Classes Event-Controlled Method Calls Figure 97: Event-Controlled Method Calls 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. © Copyright. All rights reserved. 225 Unit 5: Object-Oriented Events 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 98: Event Handling in a UML Class Diagram 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». 226 © Copyright. All rights reserved. Lesson: Implementing Events in Local Classes Event Triggering and Handling Figure 99: 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. In static methods, you can only trigger static events. 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. © Copyright. All rights reserved. 227 Unit 5: Object-Oriented Events Handling Events – Syntax Figure 100: 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. 228 © Copyright. All rights reserved. Lesson: Implementing Events in Local Classes 4. Register handler object or handler class to events at runtime. The syntax for this is SET HANDLER. Event Handler Registration Figure 101: 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. © Copyright. All rights reserved. 229 Unit 5: Object-Oriented Events Registering Event Handling – Syntax Figure 102: 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. 230 © Copyright. All rights reserved. Lesson: Implementing Events in Local Classes Event Handler Deregistration Figure 103: 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 of Events ● The visibility of an event defines where the event can be handled : © Copyright. All rights reserved. 231 Unit 5: Object-Oriented Events - PUBLIC Event can be handled anywhere. - PROTECTED Event can only be handled within its own class or its subclasses. - PRIVATE Event can only be handled within its own class. Visibility Sections of Handler Methods ● The visibility of an event handler defines where the handler method can be registered : - PUBLIC Handler method can be registered anywhere in the program. - PROTECTED Handler method can be registered within its own class or its subclasses. - PRIVATE Handler method can only be registered within its own class. Event-handler methods can only have the same or more restricted visibility than the events they refer to. 232 © 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. In the exercises for this course, when the input values include ##, replace ## with your group number. 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 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. 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. © Copyright. All rights reserved. 233 Unit 5: Object-Oriented Events 7. Where could the SET HANDLER statement be executed in the example given? Could this also be done from the main program? 8. What would the syntax have to be in case the handler would have been set from the main program? 9. Observe the execution of the program in the ABAP Debugger. 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. 234 © 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. In the exercises for this course, when the input values include ##, replace ## with your group number. 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 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. 6. Register the new handler method, so that every airplane created was added into the airplane list by the airline. © Copyright. All rights reserved. 235 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. 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. What would the syntax have to be in case the handler would have been set from the main program? SET HANDLER go_carrier->on_airplane_created FOR ALL INSTANCES. 9. 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. 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. a) Carry out this step in the usual manner. Additional information about the ABAP Debugger is available in the SAP Library. 236 © Copyright. All rights reserved. Lesson: Implementing Events in Local Classes 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 *-------------------------------------------------* * CLASS lcl_airplane IMPLEMENTATION *-------------------------------------------------* CLASS lcl_airplane IMPLEMENTATION. © Copyright. All rights reserved. 237 Unit 5: Object-Oriented Events 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 *-----------------------------------------------* CLASS lcl_cargo_plane IMPLEMENTATION. 238 © Copyright. All rights reserved. Lesson: Implementing Events in Local Classes ... 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. ENDMETHOD. "constructor METHOD lif_partner~display_partner. © Copyright. All rights reserved. 239 Unit 5: Object-Oriented Events 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. RAISE EVENT vehicle_created. ENDMETHOD. "constructor 240 © Copyright. All rights reserved. Lesson: Implementing Events in Local Classes 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, display_attributes. © Copyright. All rights reserved. 241 Unit 5: Object-Oriented Events 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 go_bus go_rental go_agency 242 TYPE TYPE TYPE TYPE TYPE REF REF REF REF REF TO TO TO TO TO lcl_vehicle, lcl_truck, lcl_bus, lcl_rental, lcl_travel_agency, © Copyright. All rights reserved. Lesson: Implementing Events in Local Classes 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 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 wrong_planetype = 1. IF sy-subrc = 0. © Copyright. All rights reserved. 243 Unit 5: Object-Oriented Events * 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( ). 244 © 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. 245 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 interface. 2. Trigger the interface event in implementing classes. 3. Handle interface event in handler class (client class). 4. Register event handling. 246 © 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. In the exercises for this course, when the input values include ##, replace ## with your group number. 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. 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. 247 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. 248 © 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. In the exercises for this course, when the input values include ##, replace ## with your group number. 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. 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? The local interface defines the event. 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. 249 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. 250 © 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. 251 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 *-------------------------------------------------* 252 © 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 253 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 ). 254 © 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. 255 Unit 5: Object-Oriented Events LESSON SUMMARY You should now be able to: ● 256 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. 257 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. 258 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. 259 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. 260 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 262 273 Lesson 2 Defining and Implementing Global Interfaces Exercise 17: Import and Implement a Global Interface 283 287 Lesson 3 Implementing Inheritance in Global Classes 298 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. 261 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 figures 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, which is the Class Builder. If 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. 262 © Copyright. All rights reserved. Lesson: Creating Global Classes Creating Global Classes in the Object Navigator Figure 104: 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. 263 Unit 6: Object-Oriented Repository Objects Definition of Attributes in a Global Class Figure 105: 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. 264 © Copyright. All rights reserved. Lesson: Creating Global Classes Create Methods in Global Class Figure 106: Definition of Methods 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 button 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. © Copyright. All rights reserved. 265 Unit 6: Object-Oriented Repository Objects Definition of Method Parameters Figure 107: 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 Methodor Next Methods button. Choose the Methods button to return to the method list. Implementation of Methods Figure 108: Implementation of Methods 266 © Copyright. All rights reserved. Lesson: Creating Global Classes 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. Displaying the Method Definition Figure 109: 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. © Copyright. All rights reserved. 267 Unit 6: Object-Oriented Repository Objects Definition of Components Using the Navigation Area Figure 110: 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. Hint: Choose Class → Print or Method → Print to print selected portions of the source text. 268 © Copyright. All rights reserved. Lesson: Creating Global Classes Class Builder Testing Environment Figure 111: 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. © Copyright. All rights reserved. 269 Unit 6: Object-Oriented Repository Objects Use of Global Classes in the ABAP Editor Figure 112: 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 113: 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. 270 © Copyright. All rights reserved. Lesson: Creating Global Classes 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 114: 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. © Copyright. All rights reserved. 271 Unit 6: Object-Oriented Repository Objects 272 © 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) . Solutions: ● 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. 273 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? 274 © 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) . Solutions: ● 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/Interfacedialog box appears c) To create the class, choose Yes. d) In the Create Class ZCL_##_HOTELdialog box, enter a short description for the global class and choose Save. e) In the Create Object Directory Entrydialog box, enter your package name and choose Save. The Prompt for transportable Workbench requestdialog box displays. f) In the Prompt for transportable Workbench requestdialog 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. 275 Unit 6: Object-Oriented Repository Objects d) In the Visibility field, use the input help to choose Private. e) In the Associated Type field, enter I. f) In the Description field, enter Output Position. g) In the Initial Value field, enter 30. 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, enter STRING. 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, enter I. 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. 276 © Copyright. All rights reserved. Lesson: Creating Global Classes b) Choose the Create Constructorbutton 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_ATTRIBUTESmethod. 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_HOTELSmethod. Choose Yes to save the class. Enter the code from the model solution. t) Choose Save, and choose 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. 277 Unit 6: Object-Oriented Repository Objects The parameters of the instance constructor will be displayed. d) Choose the Edit Long Field of Structurebutton 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 278 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. 279 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), 280 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. 281 Unit 6: Object-Oriented Repository Objects LESSON SUMMARY You should now be able to: 282 ● 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 © Copyright. All rights reserved. 283 Unit 6: Object-Oriented Repository Objects Definition of Global Interfaces Figure 115: Defining Global Interfaces 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. 284 © Copyright. All rights reserved. Lesson: Defining and Implementing Global Interfaces Implementation of Global Interfaces Figure 116: 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. © Copyright. All rights reserved. 285 Unit 6: Object-Oriented Repository Objects Import of Local Classes and Interfaces Figure 117: 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 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 Programdialog 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/Interfacesbutton. 5. Enter names for the global classes and interfaces that you want to create. 6. If applicable, remember the customer namespace. 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. 286 © 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. Templates: ● SAPBC401_GCL_S1 (program) ● CL_HOTEL (global class) Solutions: ● 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. 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. 287 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. 288 © 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. Templates: ● SAPBC401_GCL_S1 (program) ● CL_HOTEL (global class) Solutions: ● 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. 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/Interfacedialog 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 Entrydialog box displays. © Copyright. All rights reserved. 289 Unit 6: Object-Oriented Repository Objects d) In the Create Object Directory Entrydialog box, enter your package name and choose Save. A Prompt for transportable Workbench requestdialog box displays. e) In the Prompt for transportable Workbench requestdialog 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. 290 © 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 see the ZIF_##_PARTNER~DISPLAY_PARTNER METHOD. b) Double-click 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 Processingbutton. b) If the list does not display the hotel attributes, or an error occurs, run the ABAP Debugger. c) To activate the ABAP Debugger, choose Program → Execute → Debugging. d) Choose Execute, or press F8. The ABAP Debugger starts. Include: BC401_GCL_S2_AGENCY Hint: When working with this solution source code please keep in mind that you have to use your own global class ZCL_##_HOTEL and your own global interface ZIF_##_PARTNER (instead of CL_HOTEL2 and IF_PARTNER). *------------------------------------------------* * INTERFACE lif_partners © Copyright. All rights reserved. 291 Unit 6: Object-Oriented Repository Objects *------------------------------------------------* *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 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. 292 © Copyright. All rights reserved. Lesson: Defining and Implementing Global Interfaces 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 ... *---------------------------------------------------* * 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. © Copyright. All rights reserved. 293 Unit 6: Object-Oriented Repository Objects 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: 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, 294 © Copyright. All rights reserved. Lesson: Defining and Implementing Global Interfaces WRITE: ULINE. ULINE. mv_name. / 'Here comes the vehicle list: '. LOOP AT mt_vehicles INTO lo_vehicle. lo_vehicle->display_attributes( ). ENDLOOP. ENDMETHOD. "display_attributes ENDCLASS. "lcl_rental IMPLEMENTATION 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), © Copyright. All rights reserved. AT c_pos_1 mv_name, 295 Unit 6: Object-Oriented Repository Objects / '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. ***** Instance Public Method CL_HOTEL2->IF_PARTNER~DISPLAY_PARTNER METHOD if_partner~display_partner. me->display_attributes( ). ENDMETHOD. ENDCLASS. 296 © 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. 297 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: 298 ● 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 118: 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. 299 Unit 6: Object-Oriented Repository Objects Inheritance in Global Classes Figure 119: 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. 300 © Copyright. All rights reserved. Lesson: Implementing Inheritance in Global Classes Redefinition of a Method in Global Class Figure 120: Redefining an Inherited Method 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. © Copyright. All rights reserved. 301 Unit 6: Object-Oriented Repository Objects Local Types in Global Classes Figure 121: Defining a Local Type You can define local types in global classes. Global classes include 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. There are two class includes for definition and implementation of local classes, as follows: 1. Local Definitions/Implementations (formerly: Local Class Implementations): This include contains local interfaces, local class definitions, local types, and local class implementations that are not used in the private section of the global class (for example, for typing a method parameter). 2. Class Relevant Local Definitions (formerly: Local Types) This include contains local interfaces, local class definitions, local types, and local class implementations that are used in the private section of the global class (for example, for typing a method parameter). The includes can be entered by the menu Goto → Local Definitions/Implementations. 302 © Copyright. All rights reserved. Lesson: Implementing Inheritance in Global Classes Class Component Display Figure 122: Structured Display of Inherited Components To improve your understanding of inheritance and interface components, you can set the Group by Classes and Interfacesflag in the User-Specific Settingsfor 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 123: 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. © Copyright. All rights reserved. 303 Unit 6: Object-Oriented Repository Objects LESSON SUMMARY You should now be able to: 304 ● Generate UML diagrams for global classes ● Implement inheritance in global classes ● Change the display of components in global classes © 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. 305 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. 306 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 308 315 321 Lesson 2 Describing Business Add-Ins (BAdIs) 330 UNIT OBJECTIVES ● Implement a simple ALV grid ● Handle the double-click event of the ALV grid ● Describe BAdls © Copyright. All rights reserved. 307 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: 308 ● 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 124: 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. 309 Unit 7: ABAP Object-Oriented Examples Including an ALV Grid Control Instance in a Dialog Program Figure 125: 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. 310 © Copyright. All rights reserved. Lesson: Using the ABAP List Viewer (ALV) Creation of an ALV Figure 126: 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. 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 creates the field catalog automatically 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. © Copyright. All rights reserved. 311 Unit 7: ABAP Object-Oriented Examples Implementation of a Handler for the Double-Click Event Figure 127: 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. 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. 312 © Copyright. All rights reserved. Lesson: Using the ABAP List Viewer (ALV) ALV Grid Control – Reacting to a Double-Click Figure 128: 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. © Copyright. All rights reserved. 313 Unit 7: ABAP Object-Oriented Examples 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 also contains the Enjoy Demo Center , which makes it easy to use standard template programs. To find it use transaction DWDM (Development Workbench Demos). 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. 314 © 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. In the exercises for this course, when the input values include ##, replace ## with your group number. Template: SAPBC401_ALV_T1 Solution: SAPBC401_ALV_S1 Create an ALV Grid Control, and react to double-click the ALV Grid Control. Program an ALV Grid Control Program an ALV Grid Control and display 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. 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. © Copyright. All rights reserved. 315 Unit 7: ABAP Object-Oriented Examples 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 that the user clicked. 3. Create the handler instance and register the handler method CREATE OBJECT GO_HANDLER. 4. Activate and test your program. 316 © 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. In the exercises for this course, when the input values include ##, replace ## with your group number. Template: SAPBC401_ALV_T1 Solution: SAPBC401_ALV_S1 Create an ALV Grid Control, and react to double-click the ALV Grid Control. Program an ALV Grid Control Program an ALV Grid Control and display 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 as usual. 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. 317 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 Processingbutton. 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 that 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 Processingbutton. e) Carry out this step in the usual manner. Make sure that the program displays as follows: SAPBC401_ALV_S1 REPORT sapbc401_alv_s1. *-------------------------------------------------* * CLASS lcl_event_handler DEFINITION *-------------------------------------------------* 318 © Copyright. All rights reserved. Lesson: Using the ABAP List Viewer (ALV) 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. CREATE OBJECT go_container EXPORTING © Copyright. All rights reserved. 319 Unit 7: ABAP Object-Oriented Examples 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. 320 " 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. In the exercises for this course, when the input values include ##, replace ## with your group number. 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 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 that 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. 321 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 that 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 that 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 that 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 this procedure in detail. 322 © 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. In the exercises for this course, when the input values include ##, replace ## with your group number. 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 or copy the model solution from the previous exercise. a) Carry out this step as usual. 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 that 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. 323 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 that 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 that 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 that 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. 324 © 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 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. 325 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, 326 © 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. 327 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. 328 " 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. 329 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. 330 © Copyright. All rights reserved. Lesson: Describing Business Add-Ins (BAdIs) BAdI – Basics Figure 129: 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. © Copyright. All rights reserved. 331 Unit 7: ABAP Object-Oriented Examples Definition of a BAdI – Basics Figure 130: Definition of a BAdI – Basics When you define a BAdI, you must specify an interface (IF_EX_<badi>) with corresponding formally defined methods. The adapter class that is automatically generated during the interface definition (CL_EX_<badi>) 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. As of SAP Netweaver 7.0, you cannot directly create a BAdI. First, you must create an Enhancement Spot. 2. Enter the Enhancement Spotname and choose the Create button. A Create Enhancement Spotdialog displays. 3. In the Create Enhancement Spotdialog, enter a short description, and choose the Creation of an Enhancementbutton. Save the enhancement to your package. 4. Choose the Create BadI button. A Create BAdI Definitiondialog displays. 5. Enter a short description and choose the Continue button. 6. In the BAdI Definition screen area, expand the node, and double-click Interface. 332 © Copyright. All rights reserved. Lesson: Describing Business Add-Ins (BAdIs) 7. Enter your interface name ZIF_BC401_00_BADI_DEMO and press Enter. A Class/Interface dialog box displays. 8. 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. 9. Enter an instance method and a description, and activate the interface. The BAdI Calling Program Figure 131: BAdI – The Calling Program The figure, BAdI – The Calling Program, shows an example of a BAdI call. 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). © Copyright. All rights reserved. 333 Unit 7: ABAP Object-Oriented Examples ● 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 box, choose the Technical Informationbutton. 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. BAdI Implementation Figure 132: Implementation of a BAdI – SE19 334 © Copyright. All rights reserved. Lesson: Describing Business Add-Ins (BAdIs) 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<impl>. 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 <impl> (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 of 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 Spotname) and choose the Create button. 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. 335 Unit 7: ABAP Object-Oriented Examples 336 © 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. 337 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. 338 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. 339 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. 340 X A method X B structure X C object © Copyright. All rights reserved. UNIT 8 Global Classes in ABAP Development Tools Lesson 1 Developing Eclipse-Based ABAP Programs Exercise 20: Edit a Global Class and an Executable Program in ABAP Development Tools (ADT) Exercise 21: Use Refactoring Functions in ADT UNIT OBJECTIVES ● Implement Eclipse-based ABAP development ● Use quick fixes and refactoring © Copyright. All rights reserved. 341 342 349 363 Unit 8 Lesson 1 Developing Eclipse-Based ABAP Programs LESSON OVERVIEW This lesson explains how to use ABAP Development Tools (ADT). ADT is based on the Eclipse framework. ADT offers functions which are not available in the ABAP Workbench. These functions are especially useful when writing object oriented code. Business Example You have heard that SAP offers the possibility of ABAP development in Eclipse, and that developing ABAP in Eclipse is particularly useful for writing object oriented code. Therefore, you want to learn more about this possibility. LESSON OBJECTIVES After completing this lesson, you will be able to: ● Implement Eclipse-based ABAP development ● Use quick fixes and refactoring ABAP Development Tools ABAP Development Tools (ADT) is an alternative to the ABAP Workbench. ADT provides the following features: 342 ● An ABAP development experience on top of the Eclipse platform. ● An open platform for developing new ABAP-related tools. ● A set of open, language-independent, and platform-independent APIs that developers can use to build new custom tools for the ABAP environment. © Copyright. All rights reserved. Lesson: Developing Eclipse-Based ABAP Programs Figure 133: ABAP Development Tools Eclipse Based ABAP Development The ABAP Perspective Eclipse allows development in many different programming languages. To support different types of development, Eclipse contains different combinations of tools, called Perspectives. If you have ADT installed, you can switch to the ABAP perspective. Choose Window → Open Perspective → Other... → ABAP in the menu bar or choose the Open Perspectivebutton. Figure 134: Switching to the ABAP Perspective © Copyright. All rights reserved. 343 Unit 8: Global Classes in ABAP Development Tools Creation of an ABAP Project Figure 135: ADT Getting Started Creating a Project When you use ADT, you log on to an SAP back-end system and work directly with its repository objects. Therefore, the development process is exactly the same as when you use the ABAP Workbench, there is no check-out and check-in of the objects. An ABAP project serves as a container for the development objects that are stored in a particular ABAP back-end system, and contains the logon parameters for the system logon — System, Client, User, and language. You must be logged on to the system to edit an object. Within the ABAP project, you can access any development object in the repository. In addition, to make it easier to manage objects you can set up favorite packages for each project. 344 © Copyright. All rights reserved. Lesson: Developing Eclipse-Based ABAP Programs Object Editing Figure 136: ADT Editing Repository Objects The Project Explorer provides a hierarchical view of the repository, similar to the navigation area of the ABAP workbench. Under each project, you can maintain a list of favorite packages. By expanding the node System Library, you see a list of all packages. To open a specific repository object in its respective editor, double-click it. The editor is shown on the right side of the ABAP perspective. For each new object, a new tab is added. This simplifies the navigation between editors and objects. © Copyright. All rights reserved. 345 Unit 8: Global Classes in ABAP Development Tools Types of Editors Figure 137: Native Editors or Integrated SAP GUI Editors There are two kinds of editors in ADT – there is a native Eclipse implementation and an SAP GUI based implementation. In the figure, Native Editors and Integrated SAP GUI Editors, you can see an example of each of the following types: There are two types of editors in the ABAP development tools: ● Editors for which there is a native Eclipse implementation For example, ABAP Editor, an Eclipse editor ● Editors that are displayed in an in-place SAP graphical user interface (GUI) For example, ABAP transaction editor with the classic SAP GUI visualization appearing within the Eclipse environment There is no requirement to use ADT for ABAP Development, and each developer is free to choose whether to use ADT or the classic ABAP Workbench. The functions and features of Eclipse and ADT lend themselves particularly well to object-oriented programming, among these features are various built-in refactoring functions and support for unit testing. There are other tasks to which the ABAP Workbench is better suited — in particular working with module pools and screens. Documentation, Installation, and Support for ABAP Development Tools If you are looking for a local installation of ADT, you can choose from the following sources: ● 346 SAP Software Download Center (http://service.sap.com/swdc), a part of the SAP Service Marketplace. © Copyright. All rights reserved. Lesson: Developing Eclipse-Based ABAP Programs ● SAP Development Tools for Eclipse Web site (http://tools.hana.ondemand.com). You can also find other products, such as the SAP HANA studio or the tools for SAP UI5 development on this site. ● SAP Community Network pages (http://scn.sap.com/community/abap/eclipse and http://scn.sap.com/community/abap/hana). They provide documentation and support on how to install the SAP Development Tools for Eclipse. © Copyright. All rights reserved. 347 Unit 8: Global Classes in ABAP Development Tools 348 © Copyright. All rights reserved. Unit 8 Exercise 20 Edit a Global Class and an Executable Program in ABAP Development Tools (ADT) Business Example You have to create another global class, and would like to take advantage of the Quick Fix functionality available for Classes in ABAP Development Tools to complete this task in an efficient way. 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. Templates: ● SAPBC401_GCL_S1 (program) ● CL_HOTEL2 (global class) Solutions: ● SAPBC401_ADT_S1 (program) ● CL_HOTEL3 (global class) ● CL_ROOM (global class) Create an ABAP Project Create an ABAP project and add your package to the new project. 1. Launch ABAP Development Toolsand create an ABAP project. Define and Implement a Global Class Create, define, and implement a global class for rooms. Use the quick fix functionality to add the method implementations after you have defined the methods. 1. Create the global class ZCL_##_ROOM. 2. Define the following private instance attributes in the class ZCL_ROOM: Table 5: Public Instance Attributes Attribute Name Type MV_NUMBER S_ROOM_NUMBER © Copyright. All rights reserved. 349 Unit 8: Global Classes in ABAP Development Tools Attribute Name Type MV_BEDS I 3. Define the public instance constructor with the two import parameters IV_NUMBER and IV_BEDS. 4. Define the public instance method GET_BEDS with returning parameter RV_BEDS. 5. Define a public instance event ROOM_CREATED with no parameters. 6. Use the Quick Fix functionality to add the method implementations. Then implement the methods. 7. Save and activate the global class. Add Instances Rooms to the Hotel Aggregate instances of ZCL_##_ROOM in your class ZCL_##_HOTEL. Note: Edit the class ZCL_##_HOTEL for all steps of this task. 1. Define the private instance attribute MT_ROOMS with type TABLE OF REF TO ZCL_##_ROOM. 2. Define an event handler method for event ROOM_CREATED of class ZCL_##_ROOM. 3. Implement the event handler method for event ROOM_CREATED of class ZCL_##_ROOM and append the sender to the list of rooms. 4. In the constructor of ZCL_##_HOTEL, register the handler FOR ALL INSTANCES of ZCL_##_ROOM. 5. In the implementation of the DISPLAY_ATTRIBUTES method, define a local variable LV_SUM_OF_BEDS of type i and a local reference variable LO_ROOM of type REF TO ZCL_##_ROOM. 6. In the implementation of the DISPLAY_ATTRIBUTES method, edit the WRITE statement, replace the MV_BEDS attribute with the local variable. 7. Before the WRITE statement, add a loop over the aggregated rooms. Call method GET_BEDS for each room and add the result to LV_SUM_OF_BEDS. 8. Remove parameter IV_BEDS from the definition and implementation of the constructor of ZCL_##_HOTEL. Delete unused attribute MV_BEDS. 9. Save and activate the global class. Create Instances of the Room Class In your main program, create several instances of ZCL_##_ROOM to be aggregated in the instance of your hotel class. Note: Edit your main program for all steps of this task. 350 © Copyright. All rights reserved. Lesson: Developing Eclipse-Based ABAP Programs 1. Define a reference variable for instances of ZCL_##_ROOM called GO_ROOM with TYPE REF TO ZCL_##_ROOM. 2. Create several instances of the class, using the reference variable GO_ROOM. 3. The rooms are to be aggregated into the hotel through the ROOM_CREATED event. Where is the earliest point in your program where you can create the room instances? 4. Save, activate, and run your program. © Copyright. All rights reserved. 351 Unit 8 Solution 20 Edit a Global Class and an Executable Program in ABAP Development Tools (ADT) Business Example You have to create another global class, and would like to take advantage of the Quick Fix functionality available for Classes in ABAP Development Tools to complete this task in an efficient way. 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. Templates: ● SAPBC401_GCL_S1 (program) ● CL_HOTEL2 (global class) Solutions: ● SAPBC401_ADT_S1 (program) ● CL_HOTEL3 (global class) ● CL_ROOM (global class) Create an ABAP Project Create an ABAP project and add your package to the new project. 1. Launch ABAP Development Toolsand create an ABAP project. a) Choose Start → All Programs → ABAP Development Tools → ABAP Development Tools. The Workspace Launcherdialog box displays. b) In the Workspace Launcherdialog box, accept the default workspace and choose OK. c) Choose Workbench on the top right side of the editor (this is only for the first time). d) Choose Window → Perspective → Open Perspective → Other. The Open Perspectivedialog box displays. e) Select the ABAP perspective from the list. The ABAP Perspective now opens in the Eclipse editor. 352 © Copyright. All rights reserved. Lesson: Developing Eclipse-Based ABAP Programs f) Choose File → New → ABAP Project. The New ABAP Projectdialog box displays. g) In the New ABAP Projectdialog box, choose Browse. The Select Existing Systemdialog box displays. h) In the Select Existing Systemdialog box, select the correct system, for example ZME. Choose Ok. You are returned to the New ABAP Projectdialog box. i) In the New ABAP Projectdialog box, choose Next. j) Enter your Client, User, and Password as per the standard SAP logon. Choose Finish. Define and Implement a Global Class Create, define, and implement a global class for rooms. Use the quick fix functionality to add the method implementations after you have defined the methods. 1. Create the global class ZCL_##_ROOM. a) In the Eclipse Editor, choose File → New → ABAP Class. The New ABAP Class dialog box displays. b) In the New ABAP Class dialog box, ensure that your own project appears in the Project field. c) Next to the Package field, choose Browse and select your own package. d) Enter the name of the new class and a description. Choose Next and Finish. 2. Define the following private instance attributes in the class ZCL_ROOM: Table 5: Public Instance Attributes Attribute Name Type MV_NUMBER S_ROOM_NUMBER MV_BEDS I a) See source code excerpt from the model solution. 3. Define the public instance constructor with the two import parameters IV_NUMBER and IV_BEDS. a) See source code excerpt from the model solution. 4. Define the public instance method GET_BEDS with returning parameter RV_BEDS. a) See source code excerpt from the model solution. 5. Define a public instance event ROOM_CREATED with no parameters. a) See source code excerpt from the model solution. 6. Use the Quick Fix functionality to add the method implementations. Then implement the methods. a) Place the cursor on the METHODS statement and press CTRL + 1. The Quick Fix dialog box displays. b) In the Quick Fix dialog box, choose Add 2 unimplemented methods. c) Edit the method implementations, see source code extract from the model solution. © Copyright. All rights reserved. 353 Unit 8: Global Classes in ABAP Development Tools 7. Save and activate the global class. a) Save your program. b) To activate your program, on the application toolbar, choose the Activate button. Add Instances Rooms to the Hotel Aggregate instances of ZCL_##_ROOM in your class ZCL_##_HOTEL. Note: Edit the class ZCL_##_HOTEL for all steps of this task. 1. Define the private instance attribute MT_ROOMS with type TABLE OF REF TO ZCL_##_ROOM. a) See source code excerpt from the model solution. 2. Define an event handler method for event ROOM_CREATED of class ZCL_##_ROOM. a) See source code excerpt from the model solution. 3. Implement the event handler method for event ROOM_CREATED of class ZCL_##_ROOM and append the sender to the list of rooms. a) See source code excerpt from the model solution. 4. In the constructor of ZCL_##_HOTEL, register the handler FOR ALL INSTANCES of ZCL_##_ROOM. a) See source code excerpt from the model solution. 5. In the implementation of the DISPLAY_ATTRIBUTES method, define a local variable LV_SUM_OF_BEDS of type i and a local reference variable LO_ROOM of type REF TO ZCL_##_ROOM. a) See source code excerpt from the model solution. 6. In the implementation of the DISPLAY_ATTRIBUTES method, edit the WRITE statement, replace the MV_BEDS attribute with the local variable. a) See source code excerpt from the model solution. 7. Before the WRITE statement, add a loop over the aggregated rooms. Call method GET_BEDS for each room and add the result to LV_SUM_OF_BEDS. a) See source code excerpt from the model solution. 8. Remove parameter IV_BEDS from the definition and implementation of the constructor of ZCL_##_HOTEL. Delete unused attribute MV_BEDS. a) See source code excerpt from the model solution. 9. Save and activate the global class. a) Save your program. b) To activate your program, on the application toolbar, choose the Activate button. Create Instances of the Room Class In your main program, create several instances of ZCL_##_ROOM to be aggregated in the instance of your hotel class. 354 © Copyright. All rights reserved. Lesson: Developing Eclipse-Based ABAP Programs Note: Edit your main program for all steps of this task. 1. Define a reference variable for instances of ZCL_##_ROOM called GO_ROOM with TYPE REF TO ZCL_##_ROOM. a) See source code excerpt from the model solution. 2. Create several instances of the class, using the reference variable GO_ROOM. a) See source code excerpt from the model solution. 3. The rooms are to be aggregated into the hotel through the ROOM_CREATED event. Where is the earliest point in your program where you can create the room instances? After the instantiation of the hotel. 4. Save, activate, and run your program. a) Save your program. b) To activate your program, on the application toolbar, choose the Activate button. c) To run your program, on the application toolbar, choose Run As → ABAP Application. Solution: CL_ROOM **************************************************** * CLASS CL_ROOM DEFINITION * **************************************************** CLASS CL_ROOM DEFINITION PUBLIC FINAL CREATE PUBLIC. PUBLIC SECTION. METHODS constructor IMPORTING iv_number TYPE s_room_number iv_beds TYPE i. METHODS get_beds RETURNING VALUE(rv_beds) TYPE i. EVENTS room_created. PRIVATE SECTION. DATA mv_number TYPE s_room_number. DATA mv_beds TYPE i. ENDCLASS. **************************************************** * CLASS CL_ROOM IMPLEMENTATION * **************************************************** CLASS CL_ROOM IMPLEMENTATION. METHOD constructor. mv_beds = iv_beds. © Copyright. All rights reserved. 355 Unit 8: Global Classes in ABAP Development Tools mv_number = iv_number. RAISE EVENT room_created. ENDMETHOD. METHOD get_beds. rv_beds = mv_beds. ENDMETHOD. ENDCLASS. Solution: CL_HOTEL3 **************************************************** * CLASS CL_HOTEL3 DEFINITION * **************************************************** CLASS cl_hotel3 DEFINITION PUBLIC CREATE PUBLIC . PUBLIC SECTION. INTERFACES if_partner . * . METHODS constructor IMPORTING iv_name TYPE string iv_beds TYPE i METHODS display_attributes . METHODS on_room_created FOR EVENT room_created OF cl_room IMPORTING sender. CLASS-METHODS display_n_o_hotels . PRIVATE SECTION. DATA mv_name TYPE string . * DATA mv_beds TYPE i . DATA mt_rooms type table of ref to cl_room. CLASS-DATA gv_n_o_hotels TYPE i . CONSTANTS c_pos_1 TYPE i VALUE 30. ENDCLASS. **************************************************** * CLASS CL_HOTEL3 IMPLEMENTATION * **************************************************** CLASS cl_hotel3 IMPLEMENTATION. * METHOD constructor . mv_name = iv_name. mv_beds = iv_beds. ADD 1 TO gv_n_o_hotels. RAISE EVENT if_partner~partner_created. SET HANDLER on_room_created FOR ALL INSTANCES. ENDMETHOD. 356 © Copyright. All rights reserved. Lesson: Developing Eclipse-Based ABAP Programs METHOD on_room_created. APPEND sender TO mt_rooms. ENDMETHOD. * METHOD display_attributes . DATA lv_sum_of_beds type i. DAtA lo_room type ref to cl_room. ULINE. WRITE: / 'Hotel'(001), AT c_pos_1 mv_name. LOOP AT mt_rooms into lo_room. v_sum_of_beds = lv_sum_of_beds + lo_room->get_beds( ). ENDLOOP. WRITE: / 'Total number of beds:'(002), AT c_pos_1 mv_beds. / 'Total number of beds:'(002), AT c_pos_1 lv_sum_of_beds. ULINE. ULINE. SKIP. ENDMETHOD. METHOD display_n_o_hotels. WRITE: / 'Total number of hotels:'(003), gv_n_o_hotels. ENDMETHOD. METHOD if_partner~display_partner. me->display_attributes( ). ENDMETHOD. ENDCLASS. Solution: SAPBC401_ADT_S1 REPORT sapbc401_adt_s1. INCLUDE BC401_ADT_S1_AGENCY. INCLUDE BC401_ADT_S1_CARRIER. INCLUDE BC401_ADT_S1_RENTAL. DATA: go_room type ref to cl_room, go_hotel TYPE REF TO cl_hotel3, 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 hotel ****************************************** CREATE OBJECT go_hotel © Copyright. All rights reserved. 357 Unit 8: Global Classes in ABAP Development Tools EXPORTING iv_name = 'Sleep Well Hotel'. * iv_beds = 345. ******* create room ****************************************** CREATE OBJECT go_room EXPORTING iv_number = '101' iv_beds = 1. CREATE OBJECT go_room EXPORTING iv_number = '102' iv_beds = 2. CREATE OBJECT go_room EXPORTING iv_number = '103' iv_beds = 2. CREATE OBJECT go_room EXPORTING iv_number = '201' iv_beds = 3. CREATE OBJECT go_room EXPORTING iv_number = '202' iv_beds = 2. 358 © Copyright. All rights reserved. Lesson: Developing Eclipse-Based ABAP Programs Quick Fixes Developers are often required to restructure source code to make it easy to understand, to extend it, and also make it operate more efficiently. However, the consequences of restructuring can lead to broken dependencies. Refactoring eliminates the need for the tedious editing that is otherwise necessary to fix such restructuring problems. Overview of Refactoring Options ● Quick Fixes (for example, add missing method implementations) ● Method Extraction ● Deleting Unused Variables ● Renaming (for example, rename an attribute, a method, a variable, an interface) ● Changing Visibility (for example, turning local variables into attributes, making private components public) In Eclipse, Quick Fixes are shortcuts to complete tasks or resolve errors that are proposed automatically by the editor. The class editor in ADT provides quick fixes for common editor tasks. Figure 138: Example of a Quick Fix The key combination CTRL + 1 shows you available quick fixes in a dialog box. In a class, these are as follows: ● Add the implementation of a declared method. ● Add all method implementations that are still missing (for example, all methods of an interface). ● Move a method to a different visibility section within the class. © Copyright. All rights reserved. 359 Unit 8: Global Classes in ABAP Development Tools Method Extraction One important refactoring technique is method extraction. This involves moving a code block to a new method and replacing the block with a call to that new method. To perform method extraction, you must be editing a global or local ABAP class in a class pool, a program, or another type of ABAP program. Your code must be free of syntax errors before you begin. Note that method extraction is not supported in code outside of classes and that you can only extract a method within the start and end area of another method. Figure 139: Extracting a Method: Before The figure, Extracting a Method: Before, shows two methods of the same class. They both need the same existence check - although the processing that follows is different. Extracting a Method: After To increase coding reuse, you want to create a private method with the existence check, as shown in the figure, Extracting a Method: After. 360 © Copyright. All rights reserved. Lesson: Developing Eclipse-Based ABAP Programs Figure 140: Extracting a Method: After ADT supports the creation of method, CHECK_EXISTENCE, and its call in one of the original methods by using the Extract Method function. Deletion of Unused Variables Another key refactoring technique is the deletion of the unused variables that can accumulate in code over time. For example, perhaps you no longer need the code associated with a variable and deleted the code but not the variable, or you may have extracted a method, leaving behind data declarations that are outside of the scope of the extracted code. Source Code Entity Name Changes In object oriented programming, it sometimes becomes necessary to rename classes, interfaces, or any of their components. Adjusting the coding lines referencing the entity then becomes a tiresome and time consuming process, particularly if the entity is globally visible and frequently reused. ADT allows you to rename the entity, and adjust all objects that use it. © Copyright. All rights reserved. 361 Unit 8: Global Classes in ABAP Development Tools 362 © Copyright. All rights reserved. Unit 8 Exercise 21 Use Refactoring Functions in ADT Business Example You need to make further changes to your hotel class, and would like to take advantage of the refactoring functions in ABAP Development Tools to do this as efficiently as possible. Note: This exercise uses the global class ZCL_##_HOTEL completed in the previous exercises. 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: CL_HOTEL3 (global class) Solution: CL_HOTEL4 (global class) Extract a Method to Output the Total Number of Beds In your hotel class, use the extract method functionality of ABAP Development Tools to create a private method that contains the calculation and the output of the total number of beds. 1. Define a private method DISPLAY_N_O_BEDS. 2. Implement the method DISPLAY_N_O_BEDS. Make sure that you have separate WRITE statements for the output of the hotel name and the output of the total number of beds. Move the loop over the aggregated rooms to immediately before the output of the total number of rooms. 3. Extract a private method that contains the loop and the output of the total number of beds. Extract a Method to Calculate the Total Number of Beds Use the extract method functionality of ABAP Development Tools to create a private method that contains the calculation of the total number of beds, GET_N_O_BEDS. 1. Edit the DISPLAY_N_O_BEDS method of your class ZCL_##_HOTEL. Extract a private method that contains the loop only. Delete Unused Variables Delete all unused variables, activate the class, and test your program. 1. Delete all unused variables from your hotel class. 2. Save, activate, and run your program. Rename a Method Use the Rename function of Eclipse, to rename method DISPLAY_PARTNER, of your interface ZIF_##_PARTNER, to DISPLAY_PARTNER_ATTRIBUTES. © Copyright. All rights reserved. 363 Unit 8: Global Classes in ABAP Development Tools 1. Change the name of method DISPLAY_PARTNER using the Rename function. Ensure that all occurrences of the method name have changed. 2. Save and activate all affected objects. 3. Run your program. 364 © Copyright. All rights reserved. Unit 8 Solution 21 Use Refactoring Functions in ADT Business Example You need to make further changes to your hotel class, and would like to take advantage of the refactoring functions in ABAP Development Tools to do this as efficiently as possible. Note: This exercise uses the global class ZCL_##_HOTEL completed in the previous exercises. 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: CL_HOTEL3 (global class) Solution: CL_HOTEL4 (global class) Extract a Method to Output the Total Number of Beds In your hotel class, use the extract method functionality of ABAP Development Tools to create a private method that contains the calculation and the output of the total number of beds. 1. Define a private method DISPLAY_N_O_BEDS. a) See source code excerpt from the model solution. 2. Implement the method DISPLAY_N_O_BEDS. Make sure that you have separate WRITE statements for the output of the hotel name and the output of the total number of beds. Move the loop over the aggregated rooms to immediately before the output of the total number of rooms. a) See source code excerpt from the model solution. 3. Extract a private method that contains the loop and the output of the total number of beds. a) Select the LOOP ... ENDLOOP statement and the WRITE statement for the output of LV_N_O_BEDS, then on the menu bar choose Source Code → Extract Method. The Extract Method dialog box displays. b) Enter the name of the new method. For the Visibility option, select the Private radio button. Choose Next. c) Accept all the default options and choose Next. d) Analyze the suggested changes by comparing Original Source and Refactored Source. Choose Finish. Extract a Method to Calculate the Total Number of Beds Use the extract method functionality of ABAP Development Tools to create a private method that contains the calculation of the total number of beds, GET_N_O_BEDS. © Copyright. All rights reserved. 365 Unit 8: Global Classes in ABAP Development Tools 1. Edit the DISPLAY_N_O_BEDS method of your class ZCL_##_HOTEL. Extract a private method that contains the loop only. a) Select the LOOP ... ENDLOOP statement and choose Source Code → Extract Method. The Extract Method dialog box displays. b) Enter the name of the new method. For the Visibility option, select the Private radio button. Choose Next. c) Accept all the default options and choose Next. d) Analyze the suggested changes by comparing Original Source and Refactored Source. e) Choose Finish. f) For the refactored result, see source code extract for the model solution. Delete Unused Variables Delete all unused variables, activate the class, and test your program. 1. Delete all unused variables from your hotel class. a) Choose Source Code → Delete unused variables (all). 2. Save, activate, and run your program. a) Save your program. b) To activate your program, on the application toolbar, choose the Activate button. c) To run your program, on the application toolbar, choose Run As → ABAP Application. Rename a Method Use the Rename function of Eclipse, to rename method DISPLAY_PARTNER, of your interface ZIF_##_PARTNER, to DISPLAY_PARTNER_ATTRIBUTES. 1. Change the name of method DISPLAY_PARTNER using the Rename function. Ensure that all occurrences of the method name have changed. a) Set the cursor on the method name and choose Source Code → Rename The Rename Method dialog box displays. b) In the Rename Method dialog box, enter DISPLAY_PARTNER_ATTRIBUTES. Choose Next. c) Analyze the list of affected objects and choose Next. d) Analyze the changes that will be made by comparing the Original Source with the Refactored Source. Choose Finish. 2. Save and activate all affected objects. a) Save your program. b) On the menu bar, choose Project → Activate Inactive ABAP Development Objects.... The Worklist of Inactive Objectsdialog box displays. c) In the Worklist of Inactive Objectsdialog box, select all objects affected by the renaming. Choose Activate. 3. Run your program. a) To run your program, on the application toolbar, choose Run As → ABAP Application. 366 © Copyright. All rights reserved. Lesson: Developing Eclipse-Based ABAP Programs Solution: CL_HOTEL4 CLASS cl_hotel4 DEFINITION PUBLIC CREATE PUBLIC. PUBLIC SECTION. INTERFACES if_partner. . METHODS constructor IMPORTING !iv_name TYPE string. METHODS display_attributes. METHODS on_room_created FOR EVENT room_created OF cl_room IMPORTING sender. CLASS-METHODS display_n_o_hotels. PRIVATE SECTION. DATA mv_name TYPE string. DATA mt_rooms TYPE TABLE OF REF TO cl_room. METHODS display_n_o_beds. METHODS get_n_o_rooms RETURNING VALUE(rv_sum_of_beds) TYPE i. CLASS-DATA gv_n_o_hotels TYPE i. CONSTANTS c_pos_1 TYPE i VALUE 30. ENDCLASS. CLASS cl_hotel4 IMPLEMENTATION. METHOD constructor. mv_name = iv_name. ADD 1 TO gv_n_o_hotels. RAISE EVENT if_partner~partner_created. SET HANDLER on_room_created FOR ALL INSTANCES. ENDMETHOD. METHOD display_attributes. ULINE. WRITE: / 'Hotel'(001), AT c_pos_1 mv_name. display_n_o_beds( ). ULINE. SKIP. ENDMETHOD. ... METHOD display_n_o_beds. DATA lv_sum_of_beds TYPE i. lv_sum_of_beds = get_n_o_rooms( ). © Copyright. All rights reserved. 367 Unit 8: Global Classes in ABAP Development Tools * WRITE: / 'Total number of beds:'(002), AT c_pos_1 mv_beds. / 'Total number of beds:'(002), AT c_pos_1 lv_sum_of_beds. ULINE. ENDMETHOD. METHOD get_n_o_rooms. DATA lo_room TYPE REF TO cl_room. LOOP AT mt_rooms INTO lo_room. rv_sum_of_beds = rv_sum_of_beds + lo_room->get_beds( ). ENDLOOP. ENDMETHOD. ENDCLASS. 368 © Copyright. All rights reserved. Lesson: Developing Eclipse-Based ABAP Programs LESSON SUMMARY You should now be able to: ● Implement Eclipse-based ABAP development ● Use quick fixes and refactoring © Copyright. All rights reserved. 369 Unit 8: Global Classes in ABAP Development Tools 370 © Copyright. All rights reserved. Unit 8 Learning Assessment 1. When you work with ADT, you log onto the ABAP back-end system and remain logged on for your entire session. Determine whether this statement is true or false. X True X False 2. ADT contains native Eclipse editors for which kinds of repository objects? Choose the correct answers. X A ABAP programs X B Data elements X C ABAP classes X D Packages X E Text elements 3. You are creating an ABAP class in ADT and have just written the definition of a method in the public section of the class definition. You press CTRL + 1 to see the available quick fixes. Which fixes are available? Choose the correct answers. X A Add the implementation of the method X B Move the method definition to the protected or private section X C Delete the method © Copyright. All rights reserved. 371 Unit 8 Learning Assessment - Answers 1. When you work with ADT, you log onto the ABAP back-end system and remain logged on for your entire session. Determine whether this statement is true or false. X True X False 2. ADT contains native Eclipse editors for which kinds of repository objects? Choose the correct answers. X A ABAP programs X B Data elements X C ABAP classes X D Packages X E Text elements 3. You are creating an ABAP class in ADT and have just written the definition of a method in the public section of the class definition. You press CTRL + 1 to see the available quick fixes. Which fixes are available? Choose the correct answers. 372 X A Add the implementation of the method X B Move the method definition to the protected or private section X C Delete the method © Copyright. All rights reserved. UNIT 9 Class-Based Exceptions Lesson 1 Explaining Class-Based Exceptions 374 Lesson 2 Defining and Raising Exceptions Exercise 22: Implement Class-Based Exceptions 380 389 Lesson 3 Implementing Advanced Exception Handling Techniques Exercise 23: Map Exceptions to Each Other 403 411 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. 373 Unit 9 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 NetWeaver Application Server (SAP NetWeaver AS) S 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. 374 © Copyright. All rights reserved. Lesson: Explaining Class-Based Exceptions Figure 141: 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. © Copyright. All rights reserved. 375 Unit 9: Class-Based Exceptions Hierarchy of Exception Classes Figure 142: 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 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 <namespace>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. 376 © Copyright. All rights reserved. Lesson: Explaining Class-Based Exceptions Class-Based Exception Handling Figure 143: 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. 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 handler. 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. © Copyright. All rights reserved. 377 Unit 9: Class-Based Exceptions Example Syntax for Handling Predefined Exceptions Figure 144: 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 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 documentationfor each statement lists the classes whose exceptions may occur when that statement is executed. 378 © Copyright. All rights reserved. Lesson: Explaining Class-Based Exceptions Class-Based Exceptions in the Debugger Figure 145: 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 Objectbutton normally does not appear. To set the ABAP Debugger to always create the exception object, choose the respective option in the debugger settings. LESSON SUMMARY You should now be able to: ● Explain class-based exceptions ● Handle class-based exceptions ● Debug class-based exceptions © Copyright. All rights reserved. 379 Unit 9 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: 380 ● 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 146: 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 NetWeaver 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 cannot mix text from message classes and the OTR in one exception class. In releases before SAP NetWeaver 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. 381 Unit 9: 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 147: 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 &<attribute_name>&. 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. 382 © 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, if you want the exception texts to come from an existing message class, choose the With Message Class checkbox. 5. Enter a short description. 6. Do not change the default Superclass CX_STATIC_CHECK. Choose Save. The Create Object Directory Entrydialog box displays. 7. In the Create Object Directory Entrydialog box, enter your package name and choose Save. A Prompt for transportable Workbenchrequest dialog box displays. 8. In the Prompt for transportable Workbenchdialog box, accept the defaults and choose Continue. 9. 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. 10. 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 &<ATTRIBUTE_NAME>&. © Copyright. All rights reserved. 383 Unit 9: 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 148: 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 <exception_class> [EXPORTING ...]. This statement creates a new exception object that is an instance of the <exception_class> class. RAISE EXCEPTION <object_ref>. This statement uses an existing exception object that the one <object_ref> points to. The exception object was either created directly using a CREATE OBJECT statement or caught in a previous CATCH ... INTO ...statement. 384 © Copyright. All rights reserved. Lesson: Defining and Raising Exceptions 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. Exception Texts Figure 149: 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. 385 Unit 9: Class-Based Exceptions Exception Propagation Figure 150: 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. 386 © Copyright. All rights reserved. Lesson: Defining and Raising Exceptions Propagating Exceptions Over Several Hierarchy – Levels Figure 151: 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. 387 Unit 9: Class-Based Exceptions 388 © Copyright. All rights reserved. Unit 9 Exercise 22 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 Solutions: ● 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. 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 that 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. 389 Unit 9: 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. 390 © 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. 391 Unit 9 Solution 22 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 Solutions: ● 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. 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_PLANETYPE, and press Enter. A Create Class/Interfacedialog 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 Entrydialog box displays. d) In the Create Object Directory Entrydialog box, enter your package name and choose Save. A Prompt for transportable Workbench requestdialog box displays. 392 © Copyright. All rights reserved. Lesson: Defining and Raising Exceptions e) In the Prompt for transportable Workbench requestdialog 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 that 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. 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. © Copyright. All rights reserved. 393 Unit 9: Class-Based Exceptions 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. 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. 394 © Copyright. All rights reserved. Lesson: Defining and Raising Exceptions 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 Processingbutton. 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 iv_type TYPE saplane-planetype EXPORTING ev_weight TYPE saplane-weight ev_tankcap TYPE saplane-tankcap EXCEPTIONS wrong_planetype. © Copyright. All rights reserved. 395 Unit 9: Class-Based Exceptions 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. 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 396 © Copyright. All rights reserved. Lesson: Defining and Raising Exceptions 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( EXPORTING iv_name = iv_name iv_planetype = iv_planetype ). * EXCEPTIONS * wrong_planetype = 1 ). * IF sy-subrc <> 0. © Copyright. All rights reserved. 397 Unit 9: Class-Based Exceptions * * 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 ). * * * * * EXCEPTIONS wrong_planetype = 1 ). IF sy-subrc <> 0. RAISE wrong_planetype. ENDIF. mv_seats = iv_seats. ENDMETHOD. "constructor 398 © Copyright. All rights reserved. Lesson: Defining and Raising Exceptions 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. ******************* ******* create travel_agency CREATE OBJECT go_agency EXPORTING iv_name = 'Travel&Smile Travel'. © Copyright. All rights reserved. 399 Unit 9: Class-Based Exceptions ******* 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. * * * * * * * * * * 400 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, © Copyright. All rights reserved. Lesson: Defining and Raising Exceptions * * '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. 401 Unit 9: Class-Based Exceptions LESSON SUMMARY You should now be able to: 402 ● Define global exception classes ● Raise class-based exceptions ● Propagate exceptions © Copyright. All rights reserved. Unit 9 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. 403 Unit 9: Class-Based Exceptions The Hierarchy of Predefined Exception Classes Figure 152: 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. 404 © Copyright. All rights reserved. Lesson: Implementing Advanced Exception Handling Techniques 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. ● CX_NO_CHECK 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. RETRY is new as of SAP NetWeaver 7.0 EhP 2. ● From where the exception occurred using statement RESUME. RESUME is new as of SAP NetWeaver 7.0 EhP 2. 3. Raise and propagate one of the following exceptions: ● The same exception object again using RAISE EXCEPTION <obj_ref>. ● A new exception using RAISE EXCEPTION TYPE <exc_class>. © Copyright. All rights reserved. 405 Unit 9: Class-Based Exceptions The RETRY Statement Figure 153: 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. 406 © Copyright. All rights reserved. Lesson: Implementing Advanced Exception Handling Techniques Implementation of Resumable Exceptions Figure 154: 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. © Copyright. All rights reserved. 407 Unit 9: Class-Based Exceptions 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 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 155: 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 408 © Copyright. All rights reserved. Lesson: Implementing Advanced Exception Handling Techniques 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 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 156: Re-raising an Existing Exception Object You raise class-based exceptions with one of the following variants of statement RAISE EXCEPTION: ● RAISE EXCEPTION TYPE <exception_class> [EXPORTING ...] © Copyright. All rights reserved. 409 Unit 9: Class-Based Exceptions This statement creates a new exception object, which is an instance of class <exception_class>. Optionally, values can be provided for the constructor using the EXPORTING addition. ● RAISE EXCEPTION <object_ref> This statement uses an existing exception object, namely whichever exception object<object_ref> 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. 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. 410 © Copyright. All rights reserved. Unit 9 Exercise 23 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 so 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. 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. © Copyright. All rights reserved. 411 Unit 9: Class-Based Exceptions 2. Make sure that 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? Handle the New Exception 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 every time that 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. 412 © Copyright. All rights reserved. Unit 9 Solution 23 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 so 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. 413 Unit 9: 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 that 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. Handle the New Exception 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 every time that 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. * 414 METHODS: constructor IMPORTING iv_name TYPE string iv_planetype TYPE saplane-planetype RAISING cx_invalid_value, cx_invalid_planetype, © Copyright. All rights reserved. Lesson: Implementing Advanced Exception Handling Techniques 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. TRY. get_technical_attributes( EXPORTING © Copyright. All rights reserved. 415 Unit 9: Class-Based Exceptions 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 *------------------------------------------------* * CLASS lcl_cargo_plane DEFINITION *------------------------------------------------* * 416 © Copyright. All rights reserved. Lesson: Implementing Advanced Exception Handling Techniques *----------------------------------------------------* 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 *------------------------------------------------* * CLASS lcl_passenger_plane IMPLEMENTATION *------------------------------------------------* CLASS lcl_passenger_plane IMPLEMENTATION. © Copyright. All rights reserved. 417 Unit 9: Class-Based Exceptions ... 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 EXPORTING iv_name = 'Sleep Well Hotel' iv_beds = 345. 418 © Copyright. All rights reserved. Lesson: Implementing Advanced Exception Handling Techniques ******* 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 iv_name = 'US Hercules' iv_planetype = '747-200F' iv_cargo = 533. © Copyright. All rights reserved. 419 Unit 9: Class-Based Exceptions 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( ). 420 © 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. 421 Unit 9: Class-Based Exceptions 422 © Copyright. All rights reserved. Unit 9 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. 423 Unit 9: 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. 424 X A CX_STATIC_CHECK X B CX_NO_CHECK X C CX_DYNAMIC_CHECK © Copyright. All rights reserved. Unit 9: 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 be caught with addition AFTER UNWIND. 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. 425 Unit 9 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. 426 X True X False © Copyright. All rights reserved. Unit 9: 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 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. 427 Unit 9: 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. 428 X A The exception has to be caught with addition BEFORE UNWIND. X B The exception has to be caught with addition AFTER UNWIND. 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 10 Unit Testing Lesson 1 Unit Testing with ABAP Unit Exercise 24: Execute an ABAP Unit Test 430 437 UNIT OBJECTIVES ● Perform unit testing ● Use test classes and test methods ● Perform advanced ABAP unit testing © Copyright. All rights reserved. 429 Unit 10 Lesson 1 Unit Testing with ABAP Unit LESSON OVERVIEW This lesson explains how to use ABAP unit tests to verify the correct behavior of your program. Business Example You want to use ABAP Unit tests for automated, efficient testing of your ABAP coding. LESSON OBJECTIVES After completing this lesson, you will be able to: ● Perform unit testing ● Use test classes and test methods ● Perform advanced ABAP unit testing Unit Testing Unit testing is a process in which a developer ensures that the smallest testable units of their code, such as methods, are verifiable. This makes it easier to ensure quality, to refactor code, to perform regression testing, and to implement according to the test-driven development model. Unit testing is an integral part of the development phase. Figure 157: Unit Test Principle 430 © Copyright. All rights reserved. Lesson: Unit Testing with ABAP Unit Unit tests are written as local classes within the main program of a global class (class pool). They act as users of the class, and as such, they may only access its public components. Each test is implemented as a method of the class, the aim being to perform remove operations on the class under test that lead to a particular verifiable state of the class. Each test method is executed independently. Generation of Test Code ABAP Unit is a unit-testing framework that is integrated into the ABAP language. ABAP Unit tests are transported with the ABAP repository objects that they test, therefore, the source code is available in all development, testing, and production systems. Figure 158: Generation of Test Code However, this does not necessarily mean that ABAP Unit tests can be executed in every system. Profile parameter abap/test_generation specifies to which systems the load of the tests are generated. Typically, test coding is generated only in development and test systems. In production systems, test classes are excluded from the load versions to minimize the size of the loads. This prevents the test coding from having any impact on the function and performance in the production system. Advantages of Unit Testing ● Define your tests in ABAP - ● Easy testing while you develop - ● No need to learn a test script language Test tool integrated in ABAP Workbench and ABAP Development Tools (ADT) Mass Testing © Copyright. All rights reserved. 431 Unit 10: Unit Testing - ● Easy execution and evaluation - ● Evaluate which percentage of your code is covered by your tests No resource consumption in productive systems - ● Anybody can run a test without ABAP knowledge Integrated Test Coverage - ● Unit test integrated in Code Inspector and ABAP Test Cockpit Decide in which systems test coding is generated and loaded Test classification with regard for time consumption and potential damage - Identify time consuming or critical tests (e.g. tests updating persistent data) Definition of a Unit Test Class ABAP Unit tests are realized as local test classes with the required test methods in your application programs. You define local test classes by adding the FOR TESTING addition in the class definition. Further additions are used to classify the tests according to their time consumption and the impact on the data integrity. When you test your program using ABAP Unit, an instance is generated automatically for each test class, and the corresponding test methods are executed. The definition of test classes provides a clear boundary between productive coding and test coding. You can call productive coding from within the test classes. But the compiler will not allow you to access a test class from an ordinary application class. Figure 159: Definition of ABAP Unit Test Classes Test Methods Test methods are defined as instance methods without parameters (preferably private) in your local test classes. Like a test class, their definition also requires the FOR TESTING addition. 432 © Copyright. All rights reserved. Lesson: Unit Testing with ABAP Unit The Service Class CL_ABAP_UNIT_ASSERT Figure 160: Implementation of ABAP Unit Test Methods A test method contains program code to be executed for testing, followed by a check of the results derived from the test code. The content of the variables to be tested is compared against expected values by calling standard check methods of service class CL_ABAP_UNIT_ASSERT (static methods ASSERT_...). If the respective values do not correspond to the expectation, the check method can enter a note, a warning, or even an error in the test log. Method Parameters Table 6: Method Import Parameters Check methods have the following import parameters: Parameter Description act Variable to be checked exp Expected value (methods assert_equals, assert_differs) msg Message to be displayed in the log if the value does not match the expectation lev Gravity of error to be logged (class constants TOLERABLE, CRITICAL, FATAL) quit What is terminated if test fails (class constants NO, METHOD, CLASS, PROGRAM) © Copyright. All rights reserved. 433 Unit 10: Unit Testing Check methods also have a return parameter , assertion_failed (value = ’X’ /SPACE). This can be used by the test method to find out the check results. ABAP Unit Test Execution To perform an ABAP Unit test, proceed as follows: How to Perform an ABAP Unit Test ABAP Workbench ● For a Program, on the menu bar choose Program → Execute → Unit Tests. ● For a Class, on the menu bar choose Class → Run → Unit Tests. ● In the Object Name screen area, right-click the item name and choose Execute → Unit Tests. ABAP Development Tools (ADT) ● On the Project Explorermenu bar, choose Run → Run As → ABAP Unit Tests. Tools for Mass Testing ● In the ABAP Test Cockpit (ATC), use check profile with checks BC_AUNIT, BC_AUNIT_M, or BC_AUNIT_L. ● In the Code Inspector (SCI), use check variant with check List of Checks → Dynamic Tests → ABAP Unit. ABAP Unit Testing is included in both ABAP development environments. In both environments, you can perform ABAP Unit tests for single repository objects (class, function group, program) and also for a complete development package. To allow for mass testing, the Unit test framework is also included in other tools like the Code Inspector (transaction code: SCI) and the ABAP Test Cockpit (transaction code ATC). The figure, Example: Execute an ABAP Unit Test in the ABAP Workbench, illustrates how to begin a Unit test for an executable program. 434 © Copyright. All rights reserved. Lesson: Unit Testing with ABAP Unit Figure 161: Example: Execute an ABAP Unit Test in the ABAP Workbench ABAP Unit Test Results Although the tests may be carried out differently, the results are presented in a similar way. Figure 162: Example Test Result in the ABAP Workbench On the left side of the figure, Example Test Result in the ABAP Workbench, there is a list of the tests executed (test methods grouped by test classes). A red light indicates the classes and methods with errors. When you choose an entry with a red light, a list of errors is displayed in the Alerts and Messages screen area on the right side. When you click an error message, the message details are displayed in the Analysis screen area. In the Analysis area you can navigate to the source code of the test method. © Copyright. All rights reserved. 435 Unit 10: Unit Testing 436 © Copyright. All rights reserved. Unit 10 Exercise 24 Execute an ABAP Unit Test Business Example In your project some changes were made to the coding of the class LCL_CUSTOMER. Before shipment you want to make sure that the basic functionality of this class is still intact. To do this, execute the existing ABAP Unit tests. In the exercises for this course, when the input values include ##, replace ## with your group number. Template: SAPBC401_UNT_T1 Solution: SAPBC401_UNT_S1 Copy and Analyze a Program Containing an ABAP Unit Test Class Copy, activate, and analyze the template program. 1. Copy the template program, SAPBC401_UNT_T1, and all of its components to ZBC401_##_UNIT. 2. Save, check, and activate your program. 3. Analyze the program. How many local classes do you find? 4. How many test classes and test methods does it contain? 5. Execute the ABAP Unit tests for the program. 6. Analyze the result. How many errors do you find? 7. What problem situations do they refer to? © Copyright. All rights reserved. 437 Unit 10: Unit Testing Correct the Problems in the Code 1. Analyze the constructor of LCL_CUSTOMER. What is wrong with its implementation? 2. Correct the coding of the constructor implementation. 3. Save, check, and activate your program. 4. Repeat the Unit Test and verify that the errors have been removed. 438 © Copyright. All rights reserved. Unit 10 Solution 24 Execute an ABAP Unit Test Business Example In your project some changes were made to the coding of the class LCL_CUSTOMER. Before shipment you want to make sure that the basic functionality of this class is still intact. To do this, execute the existing ABAP Unit tests. In the exercises for this course, when the input values include ##, replace ## with your group number. Template: SAPBC401_UNT_T1 Solution: SAPBC401_UNT_S1 Copy and Analyze a Program Containing an ABAP Unit Test Class Copy, activate, and analyze the template program. 1. Copy the template program, SAPBC401_UNT_T1, and all of its components to ZBC401_##_UNIT. a) In the Object Navigator, in the unnamed dropdown list on the left of the screen, choose Program and enter the name of the template, SAPBC401_UNT_T1. Press Enter. b) Under Object Name in the context menu of the program name and select Copy from the context menu. The Create Program SAPBC401_UNT_T1dialog box displays. c) In the Create Program SAPBC401_UNT_T1dialog box, enter the name of the new template, ZBC401_##_UNIT. Choose Copy. The Copy Program SAPBC401_UNT_T1 to ZBC401_##_UNITdialog box displays. d) On the Copy Program SAPBC401_UNT_T1 to ZBC401_##_UNITdialog box, select all the component checkboxes. Choose Copy. The Create Object Directory Entrydialog box displays. e) In the Create Object Directory Entrydialog box, enter your package name and choose Save. The Prompt for transportable Workbench requestdialog box displays. f) In the Prompt for transportable Workbench requestdialog box, enter the request name supplied by your instructor. Choose Continue. 2. 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. 439 Unit 10: Unit Testing 3. Analyze the program. How many local classes do you find? There are two local classes. 4. How many test classes and test methods does it contain? There are two test methods in one test class. 5. Execute the ABAP Unit tests for the program. a) In the Object Navigator, in the unnamed dropdown list on the left of the screen, choose Program and enter the name of the program, then press Enter. b) On the menu bar, choose Program → Execute → ABAP Unit Tests. 6. Analyze the result. How many errors do you find? There are two errors in the program. 7. What problem situations do they refer to? The constructor of the tested class raises an unexpected exception. Correct the Problems in the Code 1. Analyze the constructor of LCL_CUSTOMER. What is wrong with its implementation? After the SELECT statement, the check of SY-SUBRC is wrong. If SY-SUBRC does not equal zero (0), the exception is raised. 2. Correct the coding of the constructor implementation. a) See source code extract from the model solution. 3. 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. 4. Repeat the Unit Test and verify that the errors have been removed. a) Repeat this step as before. Solution: SAPBC401_UDT_S1 *&--------------------------------------------------------------------* *& Report SAPBC401_UNT_S1 *&--------------------------------------------------------------------* REPORT sapbc401_unt_s1. *----------------------------------------------------------------------* * Class lcl_customer (class under test) 440 © Copyright. All rights reserved. Lesson: Unit Testing with ABAP Unit *----------------------------------------------------------------------* CLASS lcl_customer DEFINITION. PUBLIC SECTION. METHODS constructor IMPORTING iv_id TYPE s_customer RAISING cx_bc401_no_data. METHODS display_attributes. PRIVATE SECTION. DATA: mv_id TYPE s_customer, mv_name TYPE s_custname, mv_city TYPE s_city, mv_country TYPE country. ENDCLASS. CLASS lcl_customer IMPLEMENTATION. METHOD constructor. DATA ls_scustom TYPE scustom. mv_id = iv_id. SELECT SINGLE * FROM scustom INTO ls_scustom WHERE id = iv_id. * IF sy-subrc <> 0. IF sy-subrc = 0. mv_name = ls_scustom-name. mv_city = ls_scustom-city. mv_country = ls_scustom-country. ELSE. RAISE EXCEPTION TYPE cx_bc401_no_data. ENDIF. ENDMETHOD. METHOD display_attributes. WRITE: / 'Customer number'(cid), AT 40 mv_id, / 'Customer name'(nam), AT 40 mv_name, / 'City'(cit), AT 40 mv_city, / 'Country'(cny), AT 40 mv_country. ENDMETHOD. ENDCLASS. *----------------------------------------------------------------------* * class lcl_test_cust (test class) *----------------------------------------------------------------------* CLASS lcl_test_cust DEFINITION FOR TESTING DURATION SHORT © Copyright. All rights reserved. 441 Unit 10: Unit Testing RISK LEVEL HARMLESS. PRIVATE SECTION. METHODS check_constructor FOR TESTING. METHODS check_constructor_exception FOR TESTING. ENDCLASS. CLASS lcl_test_cust IMPLEMENTATION. METHOD check_constructor. DATA lo_customer TYPE REF TO lcl_customer. DATA lx_exception TYPE REF TO cx_bc401_no_data. * Create instance TRY. CREATE OBJECT lo_customer EXPORTING iv_id = '00000001'. CATCH cx_bc401_no_data INTO lx_exception. " ENDTRY. cl_aunit_assert=>assert_not_bound( EXPORTING act = lx_exception msg = 'Constructor raises exception when it should not'(rse) level = cl_aunit_assert=>critical quit = cl_aunit_assert=>method " Flusskontrolle im Fehlerfall ). ENDMETHOD. METHOD check_constructor_exception. DATA lo_customer TYPE REF TO lcl_customer. DATA lx_exception TYPE REF TO cx_bc401_no_data. * Create instance TRY. CREATE OBJECT lo_customer EXPORTING iv_id = '99999999'. CATCH cx_bc401_no_data INTO lx_exception. " ENDTRY. cl_aunit_assert=>assert_bound( EXPORTING act = lx_exception msg = 'Constructor does not raise exception when it should'(rsn) level = cl_aunit_assert=>tolerable quit = cl_aunit_assert=>method ). 442 © Copyright. All rights reserved. Lesson: Unit Testing with ABAP Unit ENDMETHOD. ENDCLASS. DATA go_customer TYPE REF TO lcl_customer. DATA gx_no_data TYPE REF TO cx_bc401_no_data. DATA gv_text TYPE string. PARAMETERS pa_cust TYPE sbook-customid. START-OF-SELECTION. TRY. . CREATE OBJECT go_customer EXPORTING iv_id = pa_cust. CATCH cx_bc401_no_data INTO gx_no_data. gv_text = gx_no_data->get_text( ). WRITE / gv_text. ENDTRY. IF go_customer IS BOUND. go_customer->display_attributes( ). ENDIF. © Copyright. All rights reserved. 443 Unit 10: Unit Testing Test Fixtures A fixture is a test configuration that is created before a test method is called, and ensures a unique test behavior. A fixture consists of test data, test objects, resources, and connections. Table 7: Private and Parameterless Methods in a Test Class To create a fixture, implement the following private and parameterless methods in a test class: Methods Description SETUP Instance method, which is executed before every single test method of the class. TEARDOWN Instance method, which is executed after every single test method of the class. CLASS_SETUP Static method, which is executed once before the first test method of the class. CLASS_TEARDOWN Static method, which is executed once after the last test method of the class. Table 8: Phase Model of Unit Test and Fixture Methods 1 Start internal session for test class 2 Class construction of test class 3 Setup of Class Fixture (method CLASS_SETUP) 4a For each Test Method: Create Test Class Instance 4b Setup of Fixture (method SETUP) 4c Execution of Test Method 4d 5 Teardown of Fixture (method TEARDOWN) Teardown of Class Fixture (method CLASS_TEARDOWN) The methods have predefined names, and are automatically called by the ABAP runtime environment when the test is executed. Hint: Due to the way in which these methods are called, all tests that use the same fixture must be included in the same test class. The fixture methods always refer to the current class. In test classes that inherit from one another, the fixture methods are executed for each class involved. The setup methods are executed from the superclasses to the subclasses, and the teardown methods from the subclasses to the superclasses. 444 © Copyright. All rights reserved. Lesson: Unit Testing with ABAP Unit Test Coverage ABAP Unit allows you to verify the thoroughness of your unit testing and easily find any untested code. To run ABAP Unit tests with code coverage measurement, choose Execute → Unit Tests With → Coverage from the development object’s context menu in the navigation area (ABAP Workbench) or Coverage As → ABAP Unit Test from the context menu in the Project Explorer (ADT). The coverage that was achieved by running the ABAP Unit tests is displayed next to the test result on an additional tab page. Figure 163: Example Unit Test Coverage ADT You can switch the display between statement coverage, branch coverage, and procedure coverage (“procedure” standing for processing block). Hint: Coverage Analysis is much better integrated into ABAP Development Tools. Whereas, in the ABAP workbench you only see a list of numbers. Types of Coverage ABAP Development Tools display the coverage in the source code editor as follows: Statement Coverage Every executable line is highlighted either green or red. Green indicates that the statement was exceeded. Red indicates that the line was not executed. Branch Coverage Branches in your code are highlighted red if they were not executed. Branches are highlighted green if they were run and resolved to both true and false. Branches are highlighted yellow if they were run but resolved only to one condition, true or false. Procedure Coverage © Copyright. All rights reserved. 445 Unit 10: Unit Testing Procedure entry points are highlighted green or red to indicate whether they were called or not. 446 © Copyright. All rights reserved. Lesson: Unit Testing with ABAP Unit LESSON SUMMARY You should now be able to: ● Perform unit testing ● Use test classes and test methods ● Perform advanced ABAP unit testing © Copyright. All rights reserved. 447 Unit 10: Unit Testing 448 © Copyright. All rights reserved. Unit 10 Learning Assessment 1. In ABAP Unit, the SETUP method is called before each individual test method. Determine whether this statement is true or false. X True X False 2. Which of the following statements about ABAP Unit tests are true? Choose the correct answers. X A Test classes are not generated in a production system X B Test methods can access the private components of the class under test X C The class under test can access the methods of the test class X D Each test method is executed independently of all of the others © Copyright. All rights reserved. 449 Unit 10 Learning Assessment - Answers 1. In ABAP Unit, the SETUP method is called before each individual test method. Determine whether this statement is true or false. X True X False 2. Which of the following statements about ABAP Unit tests are true? Choose the correct answers. 450 X A Test classes are not generated in a production system X B Test methods can access the private components of the class under test X C The class under test can access the methods of the test class X D Each test method is executed independently of all of the others © Copyright. All rights reserved. UNIT 11 Object-Oriented Design Patterns Lesson 1 Implementing Advanced Object-Oriented Techniques 453 Lesson 2 Implementing the Singleton Pattern Exercise 25: Implement the Singleton Pattern 463 467 Lesson 3 Implementing Factory Classes Using Friendship Exercise 26: Implement a Factory Class Using Friendship 476 479 Lesson 4 Implementing Persistent Objects 490 UNIT OBJECTIVES ● Implement abstract classes ● Implement final classes ● Access internal tables with object references ● Call navigation methods ● Create objects with the NEW operator ● Work with conditions on dynamic type of an object reference ● Restrict the visibility of the instance constructor ● Implement factory methods ● Implement the singleton pattern ● Implement friendship relationships ● Explain persistence services ● Examine persistent classes © Copyright. All rights reserved. 451 Unit 11: Object-Oriented Design Patterns 452 ● Create persistent objects ● Read data with persistent objects ● Create OO transactions © Copyright. All rights reserved. Unit 11 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: ● Implement abstract classes ● Implement final classes ● Access internal tables with object references ● Call navigation methods ● Create objects with the NEW operator ● Work with conditions on dynamic type of an object reference ● Restrict the visibility of the instance constructor © Copyright. All rights reserved. 453 Unit 11: Object-Oriented Design Patterns Abstract Classes Figure 164: 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. 454 © Copyright. All rights reserved. Lesson: Implementing Advanced Object-Oriented Techniques Final Classes Figure 165: 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. © Copyright. All rights reserved. 455 Unit 11: Object-Oriented Design Patterns Figure 166: 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. 456 © Copyright. All rights reserved. Lesson: Implementing Advanced Object-Oriented Techniques Read Access Using Public Attributes Figure 167: Read Access Using Public Attributes 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 side of WHERE clauses and WITH KEY additions. Therefore, public attributes are only used in some special cases in read-only mode. © Copyright. All rights reserved. 457 Unit 11: Object-Oriented Design Patterns Navigation Methods and Chain Method Calls Figure 168: 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 two methods. In more complicated object models, it is possible to chain any number of methods. 458 © Copyright. All rights reserved. Lesson: Implementing Advanced Object-Oriented Techniques Creating Objects with the NEW Operator Figure 169: Creating Objects with the NEW Operator The NEW operator creates a new instance of a class, thus replacing CREATE OBJECT. After NEW, you must specify the class that you want to instantiate. In the example in the figure, Creating Objects with the NEW operator, the pound sign (#) denotes that the class to be instantiated should be derived from the definition of the reference variable, so go_vehicle will hold a reference to an instance of the class lcl_vehicle. In the second example a subclass instance is created, therefore explicit typing with the desired subclass is necessary. Note that the NEW operator can only accept the importing parameters of the constructor, and that it is not possible to handle conventional sy-subrc-based exceptions. You handle class-based exceptions by enclosing the statement containing the NEW operator in a TRY... CATCH... ENDTRY block as normal. The NEW operator is available since Release 7.40. © Copyright. All rights reserved. 459 Unit 11: Object-Oriented Design Patterns Figure 170: Using NEW at Expression Position It is possible to use the NEW operator at many expression positions, especially as an actual parameter of a method. In the first example in the figure, Using NEW at Expression Position, an object is created just before it is needed as input for an APPEND statement. In the second example, immediately before a method call, we create a vehicle instance to use it as actual value for a method parameter. In the third example, we create the ALV instance using NEW, and, instead of passing a reference variable to the i_parent parameter, we create an instance of the container control on the fly. The inner NEW operator cannot use the pound sign to derive the type of the new variable implicitly, since the formal parameter i_parent of the ALV constructor has the type REF TO cl_gui_container, which is a superclass that may not be used as a container. Conditions on Dynamic Type of Object Reference Figure 171: Check Dynamic Type with Predicate Expression IS INSTANCE OF From Release AS ABAP 7.50, you can use the expression IS INSTANCE OFto find out whether an object reference points to an instance of a particular class. IS INSTANCE OF is true if the object in question is an instance of either the specified class or one of its subclasses. 460 © Copyright. All rights reserved. Lesson: Implementing Advanced Object-Oriented Techniques Figure 172: Special Case Distinction CASE TYPE OF for Object Reference Variables Available from Release 7.50, the control structure CASE TYPE OFallows you to distinguish between different possible types of an object reference. The corresponding WHEN TYPE block is processed if the dynamic type of the object reference variable corresponds to the given class. The optional addition INTO allows you to perform a down cast directly by specifying a reference variable. Visibility of the Instance Constructor Figure 173: 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 © Copyright. All rights reserved. 461 Unit 11: Object-Oriented Design Patterns 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. 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: 462 ● Implement abstract classes ● Implement final classes ● Access internal tables with object references ● Call navigation methods ● Create objects with the NEW operator ● Work with conditions on dynamic type of an object reference ● Restrict the visibility of the instance constructor © Copyright. All rights reserved. Unit 11 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 an instance of the class is created and has some advantages as compared to the instance constructor. Advantages of factory methods ● 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. 463 Unit 11: 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 174: 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. 464 © Copyright. All rights reserved. Lesson: Implementing the Singleton Pattern The Singleton Pattern Figure 175: 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. 465 Unit 11: Object-Oriented Design Patterns Singleton Class - Using the Static Constructor Figure 176: 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. 466 © Copyright. All rights reserved. Unit 11 Exercise 25 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. 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 that the LCL_TRAVEL_AGENCY class can only be instantiated once in your program. Implement one of the singleton patterns discussed in the course. © Copyright. All rights reserved. 467 Unit 11: Object-Oriented Design Patterns 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. 468 © Copyright. All rights reserved. Unit 11 Solution 25 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. 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 as usual. © Copyright. All rights reserved. 469 Unit 11: Object-Oriented Design Patterns Implement a Singleton Pattern Make sure that 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. ... ENDCLASS. "lcl_cargo_plane DEFINITION *------------------------------------------------* * CLASS lcl_cargo_plane IMPLEMENTATION *------------------------------------------------* CLASS lcl_cargo_plane IMPLEMENTATION. ... ENDCLASS. "lcl_cargo_plane IMPLEMENTATION 470 © Copyright. All rights reserved. Lesson: Implementing the Singleton Pattern *------------------------------------------------* * 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. "lcl_travel_agency DEFINITION *---------------------------------------------------* * 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'. © Copyright. All rights reserved. 471 Unit 11: Object-Oriented Design Patterns 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 go_carrier 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_travel_agency, lcl_vehicle, lcl_truck, lcl_bus, lcl_rental, lcl_passenger_plane, lcl_cargo_plane, lcl_carrier. START-OF-SELECTION. ******************* ******* create travel_agency *********************** * CREATE OBJECT go_agency * EXPORTING * iv_name = 'Travel&Smile Travel'. 472 © Copyright. All rights reserved. Lesson: Implementing the Singleton Pattern 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 ************************************ 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: © Copyright. All rights reserved. 473 Unit 11: Object-Oriented Design Patterns / 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( ). 474 © 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. 475 Unit 11 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 177: Definition of a Friendship Relationship Between Classes 476 © Copyright. All rights reserved. Lesson: Implementing Factory Classes Using Friendship 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 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 unilateral. 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 178: 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. 477 Unit 11: 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. 478 © Copyright. All rights reserved. Unit 11 Exercise 26 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. 3. Define a returning parameter (suggested name: RO_AIRPLANE). © Copyright. All rights reserved. 479 Unit 11: Object-Oriented Design Patterns 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? 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. 480 © 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. 481 Unit 11 Solution 26 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. a) Refer the source text excerpt from the model solution. 3. Define a returning parameter (suggested name: RO_AIRPLANE). 482 © Copyright. All rights reserved. Lesson: Implementing Factory Classes Using Friendship 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? You have to type the parameter with the common superclass of cargo planes and passenger planes, that is, TYPE REF TO lcl_airplane. a) 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 Adjust your main program. Remove the direct instantiations of airplanes and replace them by calls of the factory method. © Copyright. All rights reserved. 483 Unit 11: Object-Oriented Design Patterns 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 Processingbutton. 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 CREATE PRIVATE FRIENDS lcl_airplane_factory. ... 484 © Copyright. All rights reserved. Lesson: Implementing Factory Classes Using Friendship 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 iv_planetype iv_cargo iv_seats RETURNING © Copyright. All rights reserved. TYPE TYPE TYPE TYPE string saplane-planetype s_plan_car OPTIONAL s_seatsmax OPTIONAL 485 Unit 11: Object-Oriented Design Patterns 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 sapbc401_spc_s2. TYPE-POOLS icon. INCLUDE bc401_spc_s2_agency. INCLUDE bc401_spc_s2_carrier. 486 © Copyright. All rights reserved. Lesson: Implementing Factory Classes Using Friendship 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 ****************************** lcl_airplane_factory=>create_airplane( EXPORTING iv_name = 'LH BERLIN' iv_planetype = '747-400' © Copyright. All rights reserved. 487 Unit 11: Object-Oriented Design Patterns 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( ). 488 © 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. 489 Unit 11 Lesson 4 Implementing Persistent Objects LESSON OVERVIEW This lesson shows you how to implement persistent objects. Business Example You need to use Persistent Objects to access your database tables and also Object-Oriented (OO) transactions in your ABAP Objects programs. For this reason, you require the following knowledge: ● An understanding of persistence services ● An understanding of persistent classes ● An understanding of how to create persistent objects ● An understanding of how to read data with persistent objects ● An understanding of how to create OO transactions LESSON OBJECTIVES After completing this lesson, you will be able to: 490 ● Explain persistence services ● Examine persistent classes ● Create persistent objects ● Read data with persistent objects ● Create OO transactions © Copyright. All rights reserved. Lesson: Implementing Persistent Objects Persistence Services Figure 179: Simulation of an Object-Oriented Database Management System In principle, ABAP programs work with data and objects that are only valid at runtime. The data and objects used in ABAP programs are transient. The data in memory is temporary and disappears when the program ends. To store the data permanently and independent of the program, you must store it in a database. Theoretically, you can also use files at the operating system level. For this purpose, the persistence services for ABAP Objects were introduced in SAP NetWeaver Application Server (SAP NetWeaver AS). On request, the ABAP developer can use these services and write the current attribute values of objects as persistent to the associated transparent tables. To read the values from the tables, persistent services can be used to import the values into an object previously defined as persistent. When doing this, the persistence services use the ABAP Open SQL interface. You will use the persistence services with object-oriented programming techniques. In this way, you can simulate an object-oriented database management system using a relational database management system and ABAP Objects. Persistent Classes To use the persistence service for objects, you must create their types as persistent classes in Class Builder. The term persistent class indicates that the persistence service manages the instances of the class and their state. (Global classes are generally persistent. The question is whether or not their instances are also persistent.) To ensure that the instances of persistent classes are unique, they must contain key attributes. You can type these either as worldwide unique identification numbers (object GUID) or semantic keys. When you create a persistent class ZCL_<name>, Class Builder automatically generates methods for getting and setting its attributes. In addition, the system also generates other © Copyright. All rights reserved. 491 Unit 11: Object-Oriented Design Patterns repository objects, including the class actor (also known as the class agent) ZCA_<name>. Programs must call the methods of this class to manage the instances of persistent classes, that is, persistent objects. The class actor also performs the actual database access. It automatically inherits the required methods from the basis class ZCB_<name>. You can redefine these methods, if necessary. For example, extend database accesses. The class actor is a singleton instance and has a friendship relationship with the persistent class. Creation of Persistent Objects Figure 180: Generating and Writing to Persistent Objects In the program, you need to define a reference variable with the type of the class actor and fill it with the reference from the static attribute AGENT. You can then create a new instance of the persistent class using its method CREATE_PERSISTENT. The ABAP developer creates its interface from the definition of the key attributes of the persistent class. If a persistent object of the same persistence class with the same key attributes already exists in the program, the class-based exception CX_OS_OBJECT_EXISTING is triggered. By default, the data is saved by an asynchronous update. You must start this process by using the COMMIT WORK statement. Thus, the instances of the persistent class do not become persistent objects until after that point. 492 © Copyright. All rights reserved. Lesson: Implementing Persistent Objects Access to Persistent Objects Figure 181: Reading Persistent Objects You can load a single persistent object back into a program using the GET_PERSISTENT method. When doing so, you must pass the key values to the interface parameters so that you can uniquely restore the object. If the program does not find the object, it raises the classbased exception CX_OS_OBJECT_NOT_FOUND. You can retrieve a larger set of persistent objects by using the Query Service. It is possible to provide a selection, much like the WHERE-clause of a SELECT statement, as well as the ordering criteria. To Create Persistent Classes 1. Model the class for your persistent objects. 2. Find or create a suitable transparent table that has a field for each attribute of the class. If necessary, adapt the attributes of the class to match the technical field attributes of the transparent table. Note: There must be a primary key field in the table for each key attribute of the class or there must be a key attribute of the class for each primary key field in the table. 3. In the Class Builder, create a persistent class as described in the SAP Library. Define the persistence mapping to the table. © Copyright. All rights reserved. 493 Unit 11: Object-Oriented Design Patterns OO Transaction Figure 182: Creating an OO Transaction Code In transaction maintenance, you can create transaction code as an OO transaction. This means that you link the transaction code either to the transaction service of the ABAP Objects Services for persistent objects or a public method in a global or local class of a program. When calling this type of OO transaction, which is linked to an instance method, the system automatically creates an instance of the class in its own internal session and then executes this instance method. Caution: You still require procedural framework programs for screen fields. If the OO Transaction Modelflag is set, the system links the transaction code to the transaction service of the ABAP Objects Services. Conversely, if it is not set, you can call any method in a global or local class. Users, therefore, now have the opportunity to call methods themselves in the usual way (using menu options, command field entries, and so on). 494 © Copyright. All rights reserved. Lesson: Implementing Persistent Objects Caution: Global classes in ABAP Objects cannot contain screen definitions. Therefore, when you create a link to a global class, note the following points: ● The constructor cannot contain any IMPORTING parameters. ● You cannot process ABAP list displays. Breaking these rules will not cause a syntax error or message from the Extended Syntax Check. Instead, you will either cause a runtime error or there will be no display Therefore, you may have to resort to using methods in local program classes. Naturally, you can then use all the conventional dialog programming techniques. To Create OO Transactions You can create an OO transaction by using the following steps: 1. In the Create Transactiondialog box, enter a description in the Short Text field. 2. Choose the Method of a Class (OO Transaction)option as an Initial Object. 3. If you want to link the transaction code to a normal instance method, leave the OO Transaction Model checkbox unselected. 4. Enter the Class Name and Method. If you are using a local class, select the Local in Program checkbox and enter the program name. 5. Save the transaction code. LESSON SUMMARY You should now be able to: ● Explain persistence services ● Examine persistent classes ● Create persistent objects ● Read data with persistent objects ● Create OO transactions © Copyright. All rights reserved. 495 Unit 11: Object-Oriented Design Patterns 496 © Copyright. All rights reserved. Unit 11 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. 497 Unit 11: 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. X A Singleton X B Friendship X C Interface X D Casting 7. What should you do to use the persistence service for objects? Choose the correct answer. X A You must type it as an object GUID. X B You must type it as a semantic key. X C You must create their types as persistent classes in the Class Builder. 8. Which class-based exception is triggered if a persistent object of the same persistent class with the same key attributes already exists in the program? Choose the correct answer. 498 X A CX_SY_ZERODIVIDE X B CX_SY_MOVE_CAST_ERROR X C CX_OS_OBJECT_EXISTING X D CX_ROOT © Copyright. All rights reserved. Unit 11: Learning Assessment 9. How can you create a new instance of a persistent class? Choose the correct answer. X A By using the CREATE_PERSISTENT method of the class agent X B By using the AGENT attribute X C By using the CX_OS_OBJECT_EXISTING class-based exception X D By using the COMMIT WORK statement 10. How can you load a single persistent object back into a program? Choose the correct answer. X A By using the CREATE_PERSISTENT method X B By using the CX_OS_OBJECT_EXISTING class-based exception X C By using the Query Service X D By using the GET_PERSISTENT method 11. How can you retrieve a larger set of persistent objects? Choose the correct answer. X A By using the Query Service X B By using the CREATE_PERSISTENT method X C By using the CX_OS_OBJECT_EXISTING class-based exception X D By using the GET_PERSISTENT method © Copyright. All rights reserved. 499 Unit 11 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. 500 X True X False © Copyright. All rights reserved. Unit 11: 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. X A Singleton X B Friendship X C Interface X D Casting 7. What should you do to use the persistence service for objects? Choose the correct answer. X A You must type it as an object GUID. X B You must type it as a semantic key. X C You must create their types as persistent classes in the Class Builder. 8. Which class-based exception is triggered if a persistent object of the same persistent class with the same key attributes already exists in the program? Choose the correct answer. X A CX_SY_ZERODIVIDE X B CX_SY_MOVE_CAST_ERROR X C CX_OS_OBJECT_EXISTING X D CX_ROOT © Copyright. All rights reserved. 501 Unit 11: Learning Assessment - Answers 9. How can you create a new instance of a persistent class? Choose the correct answer. X A By using the CREATE_PERSISTENT method of the class agent X B By using the AGENT attribute X C By using the CX_OS_OBJECT_EXISTING class-based exception X D By using the COMMIT WORK statement 10. How can you load a single persistent object back into a program? Choose the correct answer. X A By using the CREATE_PERSISTENT method X B By using the CX_OS_OBJECT_EXISTING class-based exception X C By using the Query Service X D By using the GET_PERSISTENT method 11. How can you retrieve a larger set of persistent objects? Choose the correct answer. 502 X A By using the Query Service X B By using the CREATE_PERSISTENT method X C By using the CX_OS_OBJECT_EXISTING class-based exception X D By using the GET_PERSISTENT method © Copyright. All rights reserved. UNIT 12 Runtime Type Services Lesson 1 Using Runtime Type Identification (RTTI) Exercise 27: Describe Object Type Properties at Runtime 504 511 UNIT OBJECTIVES ● Explain RTTI ● Describe structure type properties at runtime ● Describe object type properties at runtime © Copyright. All rights reserved. 503 Unit 12 Lesson 1 Using Runtime Type Identification (RTTI) LESSON OVERVIEW This lesson describes how to implement run time type identification. Business Example You want to find out of which class a given object is an instance. You also want to find the properties of any given class, interface, or data type. For this reason you require the following knowledge: ● An understanding of run time type identification ● An understanding of how to query structure type properties at runtime LESSON OBJECTIVES After completing this lesson, you will be able to: 504 ● Explain RTTI ● Describe structure type properties at runtime ● Describe object type properties at runtime © Copyright. All rights reserved. Lesson: Using Runtime Type Identification (RTTI) RTTI Figure 183: Dynamic Type Analysis with RTTI Classes Since the introduction of ABAP Objects, a class-based concept has been developed, called Run Time Type Identification (RTTI). RTTI determines type attributes at runtime. RTTI includes all ABAP types and covers all the functions of the now obsolete statements DESCRIBE FIELD and DESCRIBE TABLE. RTTI includes a description class for each type with special attributes for special type attributes. The class hierarchy of the description classes corresponds to the hierarchy of types in ABAP Objects. In addition, the description classes for complex types, references, classes, and interfaces have special methods that you can use to specify references to subtypes. You can use these methods to navigate through a compound type to all its subtypes. © Copyright. All rights reserved. 505 Unit 12: Runtime Type Services RTTI – Methods and Attributes of the Root Class Figure 184: RTTI – Methods and Attributes of the Root Class To obtain a reference to a description object of a type, use the static methods of the class CL_ABAP_TYPEDESCR or the navigation methods of the special description class. The description objects are then created from one of the subclasses. At runtime, exactly one description object exists for each type. The attributes of the description object contain information on the attributes of the type. 506 © Copyright. All rights reserved. Lesson: Using Runtime Type Identification (RTTI) Structured Type RTTI Descriptions Figure 185: RTTI – Querying Structure Attributes The example in the figure RTTI – Querying Structure Attributes, shows how to identify the attributes of a structure using the subclass CL_ABAP_STRUCTDESCR from RTTI. To identify the attributes of a structure, we first define a reference to the appropriate description class. The description class has a COMPONENTS attribute that you can use to describe the components of the relevant structure. Because the COMPONENTS attribute is an internal table, you also need to define a work area with a compatible line type. The functional method call provides the reference to the description instance of the structure that you want to query. The abstract class CL_ABAP_TYPEDESCR contains the static method DESCRIBE_BY_DATA. Its returning parameter is typed as a reference to this superclass. However, since the actual parameter is a reference to the subclass CL_ABAP_STRUCTDESCR, you need to assign the object using a down-cast. You can then access the attributes of the description instance in any form. In this example, the program displays the component names as column headers. (For clarity, we have omitted the formatting options.) © Copyright. All rights reserved. 507 Unit 12: Runtime Type Services Object Type RTTI Descriptions Figure 186: RTTI – Querying Object-Type Attributes In our previous business example with the travel agency and its business partner, we specified that an instance of the vehicle rental class (LCL_RENTAL) reacts to an event by including the vehicle instance that triggered the event in a list. The triggering instances include both buses (LCL_BUS) and trucks (LCL_TRUCK). To extend the example, assume that the vehicle rental company is only interested in buses. The SENDER parameter of the event handler method contains the reference to the triggering vehicle instance. Its dynamic object type must be analyzed to determine whether the vehicle in question is a bus or a truck. A functional RTTI method call returns the reference to the description instance of the transferred vehicle instance. The abstract class CL_ABAP_TYPEDESCR has DESCRIBE_BY_OBJECT_ REF method. You type DESCRIBE_BY_OBJECT_REF returning parameter as a reference to CL_ABAP_TYPEDESCR . However, since you type the actual parameter GO_DESCR on the subclass CL_ABAP_CLASSDESCR, you need to assign the object using a down-cast. Now, you can access the attributes of the description instance in any way. The functional method GET_RELATIVE_NAME supplies the class name. 508 © Copyright. All rights reserved. Lesson: Using Runtime Type Identification (RTTI) Note: It is possible to query object type attributes at run time without using RTTI classes. For example, you can use a down-cast assignment from SENDER to a reference variable that has a LCL_BUS static type. This results in a runtime error for vehicle instances that are not buses. You can then catch this runtime error. In this case, the fact that a runtime error was not triggered is the criterion for including a vehicle into the vehicle list. © Copyright. All rights reserved. 509 Unit 12: Runtime Type Services 510 © Copyright. All rights reserved. Unit 12 Exercise 27 Describe Object Type Properties at Runtime Business Example The airline (LCL_CARRIER) wants to determine the highest cargo value of its cargo airplanes. 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_RTT_T1 Solution: SAPBC401_RTT_S1 Determine the highest cargo value for all cargo airplanes that you have entered in your application. The cargo airplanes are present in the class LCL_CARRIER (of the airline). 1. In an earlier exercise, you created method GET_MAX_CARGO to calculate the highest cargo value. RTTI can solve this more easily. Therefore, use RTTI instead of the TRYENDTRY procedure. You no longer need to catch the runtime error for a downcast, because you can determine the type of reference variable using an appropriate RTTI call. 2. Save, check, activate, and test the program. 3. Since SAP NetWeaver Application Server (SAP NetWeaver AS) 7.50, there is another option for a safe downcast, the IS INSTANCE OF condition. Comment out your solution based on a RTTI method call and instead use this condition to solve the problem. 4. Save, check, activate, and test the program again. © Copyright. All rights reserved. 511 Unit 12 Solution 27 Describe Object Type Properties at Runtime Business Example The airline (LCL_CARRIER) wants to determine the highest cargo value of its cargo airplanes. 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_RTT_T1 Solution: SAPBC401_RTT_S1 Determine the highest cargo value for all cargo airplanes that you have entered in your application. The cargo airplanes are present in the class LCL_CARRIER (of the airline). 1. In an earlier exercise, you created method GET_MAX_CARGO to calculate the highest cargo value. RTTI can solve this more easily. Therefore, use RTTI instead of the TRYENDTRY procedure. You no longer need to catch the runtime error for a downcast, because you can determine the type of reference variable using an appropriate RTTI call. a) Refer to the source code extract provided in the model solution. 2. Save, check, activate, and test 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. 3. Since SAP NetWeaver Application Server (SAP NetWeaver AS) 7.50, there is another option for a safe downcast, the IS INSTANCE OF condition. Comment out your solution based on a RTTI method call and instead use this condition to solve the problem. a) Refer to the source code extract provided in the model solution (it is commented out as this exercise deals mainly with RTTI.) 4. Save, check, activate, and test the program again. a) Carry out this step in the usual manner. Solution: Include Program BC401_RTT_S1_CARRIER *--------------------------------------------------* * CLASS lcl_airplane DEFINITION *--------------------------------------------------* 512 © Copyright. All rights reserved. Lesson: Using Runtime Type Identification (RTTI) 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 *--------------------------------------------------* * 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, get_max_cargo RETURNING value(rv_max_cargo) TYPE s_plan_car. © Copyright. All rights reserved. 513 Unit 12: Runtime Type Services 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. 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 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. DATA: lo_descr TYPE REF TO cl_abap_typedescr. LOOP AT mt_airplanes INTO lo_plane. ********************************************************************** * Solution based on RTTI method call ********************************************************************** lo_descr = cl_abap_typedescr=>describe_by_object_ref( lo_plane ). IF lo_descr->get_relative_name( ) = 'LCL_CARGO_PLANE'. lo_cargo ?= lo_plane. IF rv_max_cargo < lo_cargo->get_cargo( ). rv_max_cargo = lo_cargo->get_cargo( ). ENDIF. 514 © Copyright. All rights reserved. Lesson: Using Runtime Type Identification (RTTI) ENDIF. ********************************************************************** * Alternative solution based on condition IS INSTANCE OF ********************************************************************** * IF lo_plane IS INSTANCE OF lcl_cargo_plane. * lo_cargo ?= lo_plane. * IF rv_max_cargo < lo_cargo->get_cargo( ). * rv_max_cargo = lo_cargo->get_cargo( ). * ENDIF. * ENDIF. ********************************************************************** * Former solution: * Try to downcast each object and catch those that do not fit. ********************************************************************** * TRY. * lo_cargo ?= lo_plane. * * 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. "lcl_carrier IMPLEMENTATION © Copyright. All rights reserved. 515 Unit 12: Runtime Type Services LESSON SUMMARY You should now be able to: 516 ● Explain RTTI ● Describe structure type properties at runtime ● Describe object type properties at runtime © Copyright. All rights reserved. Unit 12 Learning Assessment 1. Which class is used to identify the attributes of a structure using Run Time Type Identification? Choose the correct answer. X A CL_ABAP_TYPEDESCR X B CL_ABAP_STRUCTDESCR X C CL_ABAP_OBJECTDESCR X D CL_ABAP_CLASSDESCR 2. Which attribute of CL_ABAP_STRUCTDESCR is used to describe the individual components of any relevant structure? Choose the correct answer. X A COMPONENTS X B TYPE_KIND X C LENGTH X D DECIMALS © Copyright. All rights reserved. 517 Unit 12 Learning Assessment - Answers 1. Which class is used to identify the attributes of a structure using Run Time Type Identification? Choose the correct answer. X A CL_ABAP_TYPEDESCR X B CL_ABAP_STRUCTDESCR X C CL_ABAP_OBJECTDESCR X D CL_ABAP_CLASSDESCR 2. Which attribute of CL_ABAP_STRUCTDESCR is used to describe the individual components of any relevant structure? Choose the correct answer. 518 X A COMPONENTS X B TYPE_KIND X C LENGTH X D DECIMALS © Copyright. All rights reserved. UNIT 13 Creation of a Comprehensive Object-Oriented Application Lesson 1 Developing a Comprehensive Object-Oriented Application Exercise 28: Create an UML Class Diagram Exercise 29: Develop a Comprehensive Object-Oriented Application 520 525 529 UNIT OBJECTIVES ● Develop a comprehensive object-oriented application © Copyright. All rights reserved. 519 Unit 13 Lesson 1 Developing a Comprehensive Object-Oriented Application LESSON OVERVIEW This lesson explains about the ways to apply the techniques of ABAP Objects to the case study. Business Example A customer has to book a flight in a travel agency but the flight is already fully booked. However, the customer is given the option of registering for the flight and being put on the waiting list. For this reason, you require the following knowledge: ● An understanding of UML diagrams ● An understanding of object-oriented programming LESSON OBJECTIVES After completing this lesson, you will be able to: ● 520 Develop a comprehensive object-oriented application © Copyright. All rights reserved. Lesson: Developing a Comprehensive Object-Oriented Application Requirements of an Object-Oriented Case Study Figure 187: Case Study – Requirements I Using the ABAP objects program, you need to implement the class diagram in the model and be able to maintain a waitlist for each flight. It is possible to maintain a waiting list for each flight row from table SFLIGHT with the key CARRID, CONNID, and FLDATE. Note: The model shown in the figure is one possible solution to the waiting list requirements described. The course participants can use their own UML class diagram, which produces a different solution. All waiting lists are to be stored in a waiting list buffer called WAIT_LIST, which is technically an internal table. In addition to the flight data, the waiting lists are to contain a list of all customers who have registered for this flight. The functions of this application are shown in the figure. © Copyright. All rights reserved. 521 Unit 13: Creation of a Comprehensive Object-Oriented Application Case Study – Requirements II Figure 188: Case Study – Requirements II The screen and functions shown are to be created in accordance with the requirement specifications. The screen layout and flow logic are already available. You now have to implement the actual flow, that is, the intelligence of the program using object-oriented techniques. Functions of Buttons Table 9: Functions of Buttons The following table lists the functions of the Buttons used in the case study: 522 Button Functions Display Displays the waiting list for the specified flight (CARRID, CONNID, FLDATE) Create Creates the waiting list for the specified flight (CARRID, CONNID, FLDATE) Delete Deletes the waiting list for the specified flight (CARRID, CONNID, FLDATE) Add Adds the customer selected on the right of the screen to the flight waiting list selected on the left Delete (Customer) Deletes the customer selected on the right of the screen from the flight displayed on the left © Copyright. All rights reserved. Lesson: Developing a Comprehensive Object-Oriented Application Button Functions Position Displays the selected customer’s position on the waiting list Customer Type Shows whether the selected customer is a private customer or a business customer (you will find the relevant information in the CUSTTYPE field of table SCUSTOM) Display customers Moved Up Displays all customers from the list who were successfully moved up from the waiting list to get a seat on the flight Status Log Displays the number of customers from the list who were successful in getting a seat on a flight © Copyright. All rights reserved. 523 Unit 13: Creation of a Comprehensive Object-Oriented Application 524 © Copyright. All rights reserved. Unit 13 Exercise 28 Create an UML Class Diagram Business Example A travel agency wants to offer its customers an additional service. If customers want to book a flight that is already fully booked, they can put their names on a waiting list for this flight. If a seat becomes free at a later date, a customer from the waiting list can be placed on the flight. This customer’s name is then removed from the waiting list. In the exercises for this course, when the input values include ##, replace ## with your group number. You can use the following suggestions but you can also choose a model of your own, which you can then use for an alternate implementation later. Perform the following steps to create a class diagram. 1. The waiting list must be the central class in the model. Use LCL_WAITLIST as the class name (ZCL_##_WAITLIST if you are using the Class Builder). The class must have the public attributes, CARRID, CONNID, FLDATE, and the private attribute, CUSTOMER_LIST. The following public methods must be defined in the UML: CONSTRUCTOR, ADD, DELETE, GET_POS, GET_FIRST and GET_WAIT_LIST. Hint: According to the encapsulation concept, you define all the attributes as private and then access these attributes of the waiting list with external methods. You need to define the attributes as public to save time and effort. 2. Customers form another class. Use LCL_CUSTOMER as the class name (ZCL_##_CUSTOMER if you are using the Class Builder). This class should have the public attribute ID and the private attributes NAME, STREET, CITY and APP_DATE. The following public methods should be defined in the UML: CONSTRUCTOR and GET_ATTRIBUTES. 3. You could simply define the buffer for the waiting lists in the main program as a normal internal table. However, you want to use one class in this case and therefore the singleton concept is used. Define the buffer for the waiting lists as singleton class LCL_BUFFER (ZCL_##_BUFFER if you are using the Class Builder). The class must contain the attribute BUFFER_LIST: the private, static attribute N_O_ENTRIES and a private, static reference to itself. The following public methods must be defined in the UML: CLASS_CONSTRUCTOR (as a static method) and DISPLAY_N_O_ENTRIES. © Copyright. All rights reserved. 525 Unit 13: Creation of a Comprehensive Object-Oriented Application Hint: According to the encapsulation concept, you need to define the BUFFER_LIST attribute as private and then access this attribute with methods from the main program. In this case, you define this attribute as public and then access it externally and directly to save time and effort. If you follow the model solution for the class diagram, you must use methods. 4. Define the relationships between these classes and assign the cardinalities (multiplicity). You also have the option of mapping the navigation options. 526 © Copyright. All rights reserved. Unit 13 Solution 28 Create an UML Class Diagram Business Example A travel agency wants to offer its customers an additional service. If customers want to book a flight that is already fully booked, they can put their names on a waiting list for this flight. If a seat becomes free at a later date, a customer from the waiting list can be placed on the flight. This customer’s name is then removed from the waiting list. In the exercises for this course, when the input values include ##, replace ## with your group number. You can use the following suggestions but you can also choose a model of your own, which you can then use for an alternate implementation later. Perform the following steps to create a class diagram. 1. The waiting list must be the central class in the model. Use LCL_WAITLIST as the class name (ZCL_##_WAITLIST if you are using the Class Builder). The class must have the public attributes, CARRID, CONNID, FLDATE, and the private attribute, CUSTOMER_LIST. The following public methods must be defined in the UML: CONSTRUCTOR, ADD, DELETE, GET_POS, GET_FIRST and GET_WAIT_LIST. Hint: According to the encapsulation concept, you define all the attributes as private and then access these attributes of the waiting list with external methods. You need to define the attributes as public to save time and effort. a) Refer to the model solution. 2. Customers form another class. Use LCL_CUSTOMER as the class name (ZCL_##_CUSTOMER if you are using the Class Builder). This class should have the public attribute ID and the private attributes NAME, STREET, CITY and APP_DATE. The following public methods should be defined in the UML: CONSTRUCTOR and GET_ATTRIBUTES. a) Refer to the model solution. 3. You could simply define the buffer for the waiting lists in the main program as a normal internal table. However, you want to use one class in this case and therefore the singleton concept is used. Define the buffer for the waiting lists as singleton class LCL_BUFFER (ZCL_##_BUFFER if you are using the Class Builder). The class must contain the attribute BUFFER_LIST: the private, static attribute N_O_ENTRIES and a private, static reference to itself. © Copyright. All rights reserved. 527 Unit 13: Creation of a Comprehensive Object-Oriented Application The following public methods must be defined in the UML: CLASS_CONSTRUCTOR (as a static method) and DISPLAY_N_O_ENTRIES. Hint: According to the encapsulation concept, you need to define the BUFFER_LIST attribute as private and then access this attribute with methods from the main program. In this case, you define this attribute as public and then access it externally and directly to save time and effort. If you follow the model solution for the class diagram, you must use methods. a) Refer to the model solution. 4. Define the relationships between these classes and assign the cardinalities (multiplicity). You also have the option of mapping the navigation options. a) See the model solution. Figure 189: Waiting List – UML Class Diagram The figure, Waiting List – UML Class Diagram, is the class diagram model solution for the Waiting List business example. 528 © Copyright. All rights reserved. Unit 13 Exercise 29 Develop a Comprehensive Object-Oriented Application Business Example Based on the business model from the previous exercise, you now need to implement the logic using ABAP Object programs. In the exercises for this course, when the input values include ##, replace ## with your group number. Convert the definitions from your class diagram into a program. If you use the suggestions proposed in this unit, follow the instructions below. If you have created your own alternate UML class diagram, you can ignore these instructions. 1. Use program SAPBC401_PRJT_WAITLIST as a template. Your program should be called ZBC401_##_PRJS_WAITLIST. Copy all Include programs from the template and rename them. You should always use the target names specified with your group number (suggested name: ZBC401_##_PRJS_INC_xxx). 2. The copied template already contains the parameters for the application to be created. Familiarize yourself with the program structure. This program contains a screen on which buttons for all of the required functions are already provided. However, with the exception of the buttons in the standard toolbar, these functions still have to be implemented. For the meaning of the individual buttons, refer to the screen shown in the figure and the explanatory text in your course notes. Note: If you have no experience with dynamic screens or dialog programming with ABAP, speak to your course instructor. © Copyright. All rights reserved. 529 Unit 13: Creation of a Comprehensive Object-Oriented Application Hint: The display of the customer data on the waiting list function code SHOW is not part of this exercise. Therefore, to save time, you can use function module BC401_DISPLAY_DATA. Later, when you are implementing this function, you should familiarize yourself with its interface and use it for display. If you have enough time, you can also use the ABAP List Viewer (ALV) Grid Control. To simplify the scenario, avoid persistent storage of the waiting list. In other words, the data is not to be saved to the database. The focus of this exercise is on the creation of a viable model for which the existing components should be examined. The main point of the exercise is not to implement the program in detail. 530 © Copyright. All rights reserved. Unit 13 Solution 29 Develop a Comprehensive Object-Oriented Application Business Example Based on the business model from the previous exercise, you now need to implement the logic using ABAP Object programs. In the exercises for this course, when the input values include ##, replace ## with your group number. Convert the definitions from your class diagram into a program. If you use the suggestions proposed in this unit, follow the instructions below. If you have created your own alternate UML class diagram, you can ignore these instructions. 1. Use program SAPBC401_PRJT_WAITLIST as a template. Your program should be called ZBC401_##_PRJS_WAITLIST. Copy all Include programs from the template and rename them. You should always use the target names specified with your group number (suggested name: ZBC401_##_PRJS_INC_xxx). a) Carry out this step in the usual manner. 2. The copied template already contains the parameters for the application to be created. Familiarize yourself with the program structure. This program contains a screen on which buttons for all of the required functions are already provided. However, with the exception of the buttons in the standard toolbar, these functions still have to be implemented. For the meaning of the individual buttons, refer to the screen shown in the figure and the explanatory text in your course notes. Note: If you have no experience with dynamic screens or dialog programming with ABAP, speak to your course instructor. © Copyright. All rights reserved. 531 Unit 13: Creation of a Comprehensive Object-Oriented Application Hint: The display of the customer data on the waiting list function code SHOW is not part of this exercise. Therefore, to save time, you can use function module BC401_DISPLAY_DATA. Later, when you are implementing this function, you should familiarize yourself with its interface and use it for display. If you have enough time, you can also use the ABAP List Viewer (ALV) Grid Control. To simplify the scenario, avoid persistent storage of the waiting list. In other words, the data is not to be saved to the database. The focus of this exercise is on the creation of a viable model for which the existing components should be examined. The main point of the exercise is not to implement the program in detail. a) The model solution provided here encapsulates the buffer with the waiting lists in class LCL_BUFFER. The waiting lists in the buffer can be accessed with public methods. It is also possible to create the buffer in the main program directly as a nonencapsulated internal table. Program SAPBC401_PRJS_WAITLIST_1 REPORT sapbc401_prjs_waitlist_1. INCLUDE sapbc401_prjs_inc_1. DATA ok_code LIKE sy-ucomm. TABLES: sdyn_conn, scustom. TYPES: ty_wait_list TYPE STANDARD TABLE OF REF TO lcl_waitlist. DATA: r_buffer TYPE REF TO lcl_buffer, r_customer TYPE REF TO lcl_customer, r_waitlist TYPE REF TO lcl_waitlist, r_exc TYPE REF TO cx_root. DATA: wa_sflight TYPE sflight. LOAD-OF-PROGRAM. *---------------------------------------------------* Instantiate the Buffer which is a singleton r_buffer = lcl_buffer=>get_buffer_ref( ). * some dynpro initializations sdyn_conn-carrid = 'LH'. sdyn_conn-connid = '0400'. sdyn_conn-fldate = '20040710'. scustom-id = '00003392'. START-OF-SELECTION. *---------------------------------------------------CALL SCREEN 100. 532 © Copyright. All rights reserved. Lesson: Developing a Comprehensive Object-Oriented Application INCLUDE sapbc401_prjs_waitlist_o01. Solution - Include Program SAPBC401_PRJS_WAITLIST_I01 *-------------------------------------------------* * INCLUDE BC401_CSS1_WAITLIST_I01 . *-------------------------------------------------* *-------------------------------------------------* * Module check_and_create_cust INPUT *-------------------------------------------------* MODULE check_and_create_cust INPUT. SELECT SINGLE name street city FROM scustom INTO CORRESPONDING FIELDS OF scustom WHERE id = scustom-id. IF sy-subrc <> 0. CLEAR: scustom-name, scustom-city. MESSAGE e916(BC401) WITH scustom-id. * Customer number & does not exist. Please correct ! ENDIF. ENDMODULE. " check_and_create_cust INPUT *-------------------------------------------------* * Module user_command_0100 INPUT *-------------------------------------------------* MODULE user_command_0100 INPUT. DATA: text TYPE string. DATA: n_o_lines TYPE i. DATA: save_ok TYPE sy-ucomm. CLEAR r_waitlist. save_ok = ok_code. CLEAR ok_code. CASE save_ok. WHEN 'BACK'. LEAVE TO SCREEN 0. WHEN 'CREATE'. TRY. r_buffer->create_wait_list( EXPORTING im_carrid = sdyn_conn-carrid im_connid = sdyn_conn-connid im_fldate = sdyn_conn-fldate ). MESSAGE s905(BC401) WITH sdyn_conn-carrid sdyn_conn-connid sdyn_conn-fldate. CATCH cx_wait_list INTO r_exc. text = r_exc->get_text( ). MESSAGE s901(BC401) WITH sdyn_conn-carrid sdyn_conn-connid. ENDTRY. WHEN 'SHOW'. DATA: it_customer_list TYPE STANDARD TABLE OF bc401_typd_cust. DATA: wa_cust LIKE LINE OF it_customer_list. DATA: r_customer_list TYPE TABLE OF REF TO lcl_customer. © Copyright. All rights reserved. 533 Unit 13: Creation of a Comprehensive Object-Oriented Application DATA: r_cust TYPE REF TO lcl_customer. r_waitlist = r_buffer->get_wait_list( im_carrid = sdyn_conn-carrid im_connid = sdyn_conn-connid im_fldate = sdyn_conn-fldate ). IF r_waitlist IS BOUND. r_waitlist->get_wait_list( IMPORTING ex_wait_list = r_customer_list ). n_o_lines = LINES( r_customer_list ). IF n_o_lines > 0. CLEAR it_customer_list. LOOP AT r_customer_list INTO r_cust. r_cust->get_attributes( IMPORTING ex_cust = wa_cust ). INSERT wa_cust INTO TABLE it_customer_list. ENDLOOP. * show dynpro with all customers and their data CALL FUNCTION 'BC401_DISPLAY_DATA' EXPORTING im_list = it_customer_list. ELSE. MESSAGE s903(BC401) WITH sdyn_conn-carrid sdyn_conn-connid sdyn_conn-fldate. * The waitinglist for flight &1 &2 &3 has no entries ! ENDIF. ELSE. MESSAGE s902(BC401) WITH sdyn_conn-carrid sdyn_conn-connid sdyn_conn-fldate. * There is no waitinglist for flight Flug &1 &2 &3 ! ENDIF. WHEN 'DELETE'. TRY. r_buffer->delete_wait_list( EXPORTING im_carrid = sdyn_conn-carrid im_connid = sdyn_conn-connid im_fldate = sdyn_conn-fldate ). MESSAGE s906(BC401) WITH sdyn_conn-carrid sdyn_conn-connid sdyn_conn-fldate. * Waitinglist for flight &1 &2 &3 has been deleted * succesfully CATCH cx_wait_list INTO r_exc. text = r_exc->get_text( ). MESSAGE text TYPE 'S'. ENDTRY. WHEN 'FIRST'. r_waitlist = r_buffer->get_wait_list( im_carrid = sdyn_conn-carrid im_connid = sdyn_conn-connid im_fldate = sdyn_conn-fldate ). IF r_waitlist IS BOUND. TRY. r_waitlist->get_first( ). 534 © Copyright. All rights reserved. Lesson: Developing a Comprehensive Object-Oriented Application MESSAGE s907(BC401) WITH sdyn_conn-carrid sdyn_conn-connid sdyn_conn-fldate. * The first customer on waitinglist &1 &2 &3 * has been deleted. CATCH cx_wait_list INTO r_exc. text = r_exc->get_text( ). MESSAGE text TYPE 'I'. ENDTRY. ELSE. MESSAGE s902(BC401) WITH sdyn_conn-carrid sdyn_conn-connid sdyn_conn-fldate. * There is no waitinglist for flight &1 &2 &3 ! ENDIF. WHEN 'ADD'. IF scustom-id IS INITIAL. MESSAGE s908(BC401). * Please enter a correct customernumber ! EXIT. ENDIF. r_waitlist = r_buffer->get_wait_list( im_carrid = sdyn_conn-carrid im_connid = sdyn_conn-connid im_fldate = sdyn_conn-fldate ). IF r_waitlist IS BOUND. TRY. CREATE OBJECT r_customer EXPORTING im_id = scustom-id im_name = scustom-name im_street = scustom-street im_city = scustom-city im_app_date = sy-datum. r_waitlist->add( r_customer ). MESSAGE s910(BC401) WITH scustom-id sdyn_conn-carrid sdyn_conn-connid sdyn_conn-fldate. * Customer &1 was appended to waitinglist for * flight &2 &3 &4 CATCH cx_wait_list INTO r_exc. text = r_exc->get_text( ). MESSAGE text TYPE 'I'. ENDTRY. ELSE. MESSAGE s902(BC401) WITH sdyn_conn-carrid sdyn_conn-connid sdyn_conn-fldate. * There is no waitinglist for flight &1 &2 &3 ! ENDIF. WHEN 'DEL'. IF scustom-id IS INITIAL. MESSAGE s908(BC401). * Please select a valid customer number ! EXIT. ENDIF. r_waitlist = r_buffer->get_wait_list( im_carrid = sdyn_conn-carrid im_connid = sdyn_conn-connid © Copyright. All rights reserved. 535 Unit 13: Creation of a Comprehensive Object-Oriented Application im_fldate = sdyn_conn-fldate ). IF r_waitlist IS BOUND. IF NOT r_customer IS BOUND. MESSAGE s911(BC401). ELSE. TRY. r_waitlist->delete( r_customer ). MESSAGE s912(BC401) WITH scustom-id sdyn_conn-carrid sdyn_conn-connid sdyn_conn-fldate. * Customer &1 was deleted from waitinglist for flight &2 &3 * &4 ! CATCH cx_wait_list INTO r_exc. text = r_exc->get_text( ). MESSAGE text TYPE 'I'. ENDTRY. ENDIF. ELSE. MESSAGE s902(BC401) WITH sdyn_conn-carrid sdyn_conn-connid sdyn_conn-fldate. * There is no waitinglist for flight &1 &2 &3 ! ENDIF. WHEN 'POS'. DATA pos LIKE sy-tabix. DATA flight TYPE string. DATA fldate(10) TYPE c. IF scustom-id IS INITIAL. MESSAGE s908(BC401). * Please enter a valid customernumber ! EXIT. ENDIF. r_waitlist = r_buffer->get_wait_list( im_carrid = sdyn_conn-carrid im_connid = sdyn_conn-connid im_fldate = sdyn_conn-fldate ). IF r_waitlist IS BOUND. TRY. CREATE OBJECT r_customer EXPORTING im_id = scustom-id im_name = scustom-name im_street = scustom-street im_city = scustom-city im_app_date = sy-datum. r_waitlist->get_pos( EXPORTING im_customer = r_customer IMPORTING ex_pos = pos ). WRITE sdyn_conn-fldate TO fldate. CONCATENATE sdyn_conn-carrid sdyn_conn-connid fldate INTO flight SEPARATED BY space. MESSAGE i913(BC401) WITH scustom-id flight pos. * Customer &1 is held on list for flight &2 at position &3 CATCH cx_wait_list INTO r_exc. text = r_exc->get_text( ). MESSAGE text TYPE 'I'. ENDTRY. 536 © Copyright. All rights reserved. Lesson: Developing a Comprehensive Object-Oriented Application ELSE. MESSAGE s902(BC401) WITH sdyn_conn-carrid sdyn_conn-connid sdyn_conn-fldate. * There is no waitinglist for flight &1 &2 &3 ! ENDIF. ENDCASE. ENDMODULE. " user_command_0100 INPUT *--------------------------------------------------* * Module check_flight INPUT *--------------------------------------------------* MODULE check_flight INPUT. SELECT SINGLE * FROM sflight INTO wa_sflight WHERE carrid = sdyn_conn-carrid AND connid = sdyn_conn-connid AND fldate = sdyn_conn-fldate. IF sy-subrc <> 0. MESSAGE e904(BC401). * Please select a valid flight ! ENDIF. ENDMODULE. *--------------------------------------------------* * Module exit INPUT *--------------------------------------------------* MODULE exit INPUT. CASE ok_code. WHEN 'CANCEL'. CLEAR: scustom, sdyn_conn. LEAVE TO SCREEN 100. WHEN 'EXIT'. LEAVE PROGRAM. ENDCASE. ENDMODULE. " exit INPUT Solution - Include Program SAPBC401_PRJS_WAITLIST_O01 *-------------------------------------------------* * Include SAPBC401_PRJS_WAITLIST_O01 *-------------------------------------------------* *-------------------------------------------------* * Module STATUS_0100 OUTPUT *-------------------------------------------------* MODULE status_0100 OUTPUT. SET PF-STATUS 'DYNPRO_100'. SET TITLEBAR 'TITLE_100'. ENDMODULE. " STATUS_0100 OUTPUT *-----------------------------------------------* * Module clear_ok_code OUTPUT *-----------------------------------------------* MODULE clear_ok_code OUTPUT. CLEAR ok_code. ENDMODULE. " clear_ok_code OUTPUT © Copyright. All rights reserved. 537 Unit 13: Creation of a Comprehensive Object-Oriented Application Solution - Include Program SAPBC401_PRJS_INC_1 *--------------------------------------------------* * Include SAPBC401_PRJS_INC_1 *--------------------------------------------------* *--------------------------------------------------* * CLASS lcl_customer DEFINITION *--------------------------------------------------* CLASS lcl_customer DEFINITION. PUBLIC SECTION. METHODS constructor IMPORTING im_id TYPE s_customer im_name TYPE s_custname im_street TYPE s_street im_city TYPE city im_app_date TYPE d. METHODS: get_attributes EXPORTING ex_cust TYPE bc401_typd_cust. DATA: id TYPE s_customer READ-ONLY. PRIVATE SECTION. DATA: name TYPE s_custname, street TYPE s_street, city TYPE city, app_date TYPE d. ENDCLASS. "lcl_customer DEFINITION *---------------------------------------------------* * CLASS lcl_customer IMPLEMENTATION *---------------------------------------------------* CLASS lcl_customer IMPLEMENTATION. METHOD constructor. id = im_id. name = im_name. street = im_street. city = im_city. app_date = im_app_date. ENDMETHOD. "constructor METHOD get_attributes. ex_cust-id = id. ex_cust-name = name. ex_cust-street = street. ex_cust-city = city. ex_cust-app_date = app_date. ENDMETHOD. "get_attributes ENDCLASS. "lcl_customer IMPLEMENTATION *---------------------------------------------------* * CLASS lcl_waitlist DEFINITION *---------------------------------------------------* CLASS lcl_waitlist DEFINITION. PUBLIC SECTION. TYPES ty_customer_list TYPE STANDARD TABLE OF REF TO lcl_customer WITH DEFAULT KEY. 538 © Copyright. All rights reserved. Lesson: Developing a Comprehensive Object-Oriented Application METHODS constructor IMPORTING im_carrid TYPE sflight-carrid im_connid TYPE sflight-connid im_fldate TYPE sflight-fldate. METHODS add IMPORTING im_customer TYPE REF TO lcl_customer RAISING cx_wait_list. METHODS delete IMPORTING im_customer TYPE REF TO lcl_customer RAISING cx_wait_list. METHODS get_pos IMPORTING im_customer TYPE REF TO lcl_customer EXPORTING ex_pos LIKE sy-tabix RAISING cx_wait_list. METHODS get_wait_list EXPORTING ex_wait_list TYPE ty_customer_list. METHODS get_first RAISING cx_wait_list. DATA: carrid TYPE sflight-carrid READ-ONLY, connid TYPE sflight-connid READ-ONLY, fldate TYPE sflight-fldate READ-ONLY. PRIVATE SECTION. DATA: customer_list TYPE ty_customer_list. ENDCLASS. "lcl_waitlist DEFINITION *------------------------------------------* * CLASS lcl_waitlist IMPLEMENTATION *------------------------------------------* CLASS lcl_waitlist IMPLEMENTATION. METHOD constructor. carrid = im_carrid. connid = im_connid. fldate = im_fldate. ENDMETHOD. "constructor METHOD get_wait_list. ex_wait_list = customer_list. ENDMETHOD. "get_wait_list METHOD add. READ TABLE customer_list WITH KEY table_line->id = im_customer->id TRANSPORTING NO FIELDS. *** customer is not in wait_list IF sy-subrc <> 0. INSERT im_customer INTO TABLE customer_list. ELSE. *** customer is already in wait_list for this flight RAISE EXCEPTION TYPE cx_wait_list EXPORTING textid = cx_wait_list=>cx_wait_list_customer_there customer = im_customer->id carrid = carrid connid = connid © Copyright. All rights reserved. 539 Unit 13: Creation of a Comprehensive Object-Oriented Application fldate ENDIF. = fldate. ENDMETHOD. "add METHOD get_first. DATA r_cust TYPE REF TO lcl_customer. READ TABLE customer_list INTO r_cust INDEX 1. IF sy-subrc <> 0. RAISE EXCEPTION TYPE cx_wait_list EXPORTING textid = cx_wait_list=>cx_wait_list_no_entry carrid = carrid connid = connid fldate = fldate. ELSE. DELETE customer_list INDEX 1. ENDIF. ENDMETHOD. "get_first METHOD delete. DELETE customer_list WHERE table_line->id = im_customer->id. IF sy-subrc <> 0. RAISE EXCEPTION TYPE cx_wait_list EXPORTING textid = cx_wait_list=>cx_wait_list_customer_notthere customer = im_customer->id carrid = carrid connid = connid fldate = fldate. ENDIF. ENDMETHOD. "delete METHOD get_pos. READ TABLE customer_list WITH KEY table_line->id = im_customer->id TRANSPORTING NO FIELDS. IF sy-subrc = 0. ex_pos = sy-tabix. ELSE. RAISE EXCEPTION TYPE cx_wait_list EXPORTING textid = cx_wait_list=>cx_wait_list_customer_notthere customer = im_customer->id carrid = carrid connid = connid fldate = fldate. ENDIF. ENDMETHOD. "get_pos *-------------------------------------------------* CLASS lcl_buffer DEFINITION *-------------------------------------------------* implemented as SINGLETON, should exist only once *-------------------------------------------------CLASS lcl_buffer DEFINITION CREATE PRIVATE. 540 © Copyright. All rights reserved. Lesson: Developing a Comprehensive Object-Oriented Application PUBLIC SECTION. CLASS-METHODS: class_constructor. CLASS-METHODS: get_buffer_ref RETURNING value(re_buffer) TYPE REF TO lcl_buffer. METHODS: create_wait_list IMPORTING im_carrid TYPE s_carr_id im_connid TYPE s_conn_id im_fldate TYPE sflight-fldate RETURNING value(re_waitlist) TYPE REF TO lcl_waitlist RAISING cx_wait_list. METHODS: get_wait_list IMPORTING im_carrid TYPE s_carr_id im_connid TYPE s_conn_id im_fldate TYPE sflight-fldate RETURNING value(re_waitlist) TYPE REF TO lcl_waitlist. METHODS: delete_wait_list IMPORTING im_carrid TYPE s_carr_id im_connid TYPE s_conn_id im_fldate TYPE sflight-fldate RAISING cx_wait_list. METHODS: delete_all_wait_lists. PRIVATE SECTION. CLASS-DATA: r_buffer TYPE REF TO lcl_buffer. DATA: wait_list TYPE STANDARD TABLE OF REF TO lcl_waitlist. ENDCLASS. "lcl_buffer DEFINITION *-------------------------------------------------* CLASS lcl_buffer IMPLEMENTATION *-------------------------------------------------CLASS lcl_buffer IMPLEMENTATION. METHOD class_constructor. CREATE OBJECT r_buffer. ENDMETHOD. "class_constructor METHOD get_buffer_ref. re_buffer = r_buffer. ENDMETHOD. "get_buffer_ref METHOD create_wait_list. DATA: r_waitlist TYPE REF TO lcl_waitlist. r_waitlist = get_wait_list( im_carrid = im_carrid im_connid = im_connid im_fldate = im_fldate ). IF NOT r_waitlist IS BOUND. CREATE OBJECT r_waitlist EXPORTING im_carrid = im_carrid im_connid = im_connid © Copyright. All rights reserved. 541 Unit 13: Creation of a Comprehensive Object-Oriented Application im_fldate = im_fldate. INSERT r_waitlist INTO TABLE wait_list. ELSE. RAISE EXCEPTION TYPE cx_wait_list EXPORTING carrid = im_carrid connid = im_connid fldate = im_fldate textid = cx_wait_list=>cx_wait_list_exists. ENDIF. ENDMETHOD. "create_wait_list METHOD get_wait_list. READ TABLE wait_list INTO re_waitlist WITH KEY table_line->carrid = im_carrid table_line->connid = im_connid table_line->fldate = im_fldate. ENDMETHOD. "get_wait_list METHOD delete_wait_list. DATA: r_waitlist TYPE REF TO lcl_waitlist. r_waitlist = get_wait_list( im_carrid = im_carrid im_connid = im_connid im_fldate = im_fldate ). IF NOT r_waitlist IS BOUND. RAISE EXCEPTION TYPE cx_wait_list EXPORTING carrid = im_carrid connid = im_connid fldate = im_fldate. ELSE. DELETE wait_list WHERE table_line->carrid = im_carrid AND table_line->connid = im_connid AND table_line->fldate = im_fldate. ENDIF. ENDMETHOD. "delete_wait_list METHOD delete_all_wait_lists. CLEAR wait_list. *ATTENTION: in our case, this also deletes all *customer-objects. * --> COMPOSITION in class-diagram ? ENDMETHOD. "delete_all_wait_lists ENDCLASS. "lcl_buffer IMPLEMENTATION Flow Logic of Screen 100 PROCESS BEFORE OUTPUT. MODULE status_0100. MODULE clear_ok_code. PROCESS AFTER INPUT. MODULE exit AT EXIT-COMMAND. CHAIN. FIELD: sdyn_conn-carrid, sdyn_conn-connid, 542 © Copyright. All rights reserved. Lesson: Developing a Comprehensive Object-Oriented Application sdyn_conn-fldate. MODULE check_flight. ENDCHAIN. CHAIN. FIELD: scustom-id, scustom-name, scustom-city. MODULE check_and_create_cust. " ON CHAIN-REQUEST. ENDCHAIN. MODULE user_command_0100. © Copyright. All rights reserved. 543 Unit 13: Creation of a Comprehensive Object-Oriented Application LESSON SUMMARY You should now be able to: ● 544 Develop a comprehensive object-oriented application © Copyright. All rights reserved. Unit 13 Learning Assessment 1. In the case study, when we use one class to define the buffer for the waiting lists for all flights, what concept are we implementing? Choose the correct answer. X A Superclass X B Singleton class X C Subclass X D Friends © Copyright. All rights reserved. 545 Unit 13 Learning Assessment - Answers 1. In the case study, when we use one class to define the buffer for the waiting lists for all flights, what concept are we implementing? Choose the correct answer. 546 X A Superclass X B Singleton class X C Subclass X D Friends © Copyright. All rights reserved.