Friday, March 21, 2025

Day 3 - Persistence Service

 

DAY 1 - Introduction - OOPs Concept, Local Class and Class Components

Day 2 - Global Class and OOPs Features


1.Persistence Service:

  1. In SAP ABAP, the Persistence Service is used to store the current state of an object permanently in the database. 
  2. By default, an object's lifetime is limited to the duration of a program’s execution. Once the program ends, the memory allocated to the object is cleared by the garbage collector. However, with Persistence Service, objects can be made permanent, allowing data to be stored and retrieved from the database.
  3. Persistence service enables CRUD (Create, Read, Update, Delete) operations on database tables
  4.  Persistence service implemented using Persistence Classes in ABAP.
  5. Persistence Classes are always created globally in the SE24.
  6. Persistence Class follows strict naming convention:
    • ZCL_<classname> or YCL_<classname> 
  7. Whenever a persistence class is created, SAP automatically generates two internal supporting classes:
    • Base Agent Class (ZCB_<classname>)
      • An abstract class and friend class to the persistence class.
      • Serves as the superclass of the Actor/Agent class.
    • Actor/Agent Class (ZCA_<classname>)
      • Created as a singleton class, meaning only one instance of it exists.
      • private class that inherits from the Base Agent class.
  8. By default, the persistence class implements the IF_OS_STATE interface, which manages object state storage in the database.

Types of Persistence Implementation

Persistence Service can be implemented in two ways:

  1. Business Key Identity – Uses a database table's primary key as a unique identifier for objects.
  2. GUID (Global Unique Identifier) – Uses a system-generated unique ID for object identification.

Steps To Create Persistence Service with Business Key Identity

Step 1: Create a Database Table

Consider a table ZAK_EMP, which stores employee details:

Field        Data Element        Type        Length
    Empno (PK)        ZAK_EMPNO        INT4        10
    Ename        ZAK_ENAME        CHAR        20
    Empdesig        ZAK_DESIG        CHAR        20

Step 2: Create a Persistence Class

create a Persistence Class (e.g., ZCL_ZAK_PERSISTENCE), SAP will automatically generate two additional classes and an interface:
  1. Base Agent Class (e.g., ZCB_ZAK_PERSISTENCE): An abstract class that provides core persistence functionality.
  2. Actor/Agent Class (e.g., ZCA_ZAK_PERSISTENCE): A singleton class that interacts with the persistence layer and manages CRUD operations.
  3. Interface (IF_OS_STATE): Automatically implemented by the Persistence Class, enabling the object state management for CRUD operations.
Step 3: Map the Class to the Database Table

Navigate to GOTO → Persistence Representation in Class Builder.

  • Must Map all fields of ZAK_EMP to the persistence class.
  • SAP generates GET_ methods for all attributes and SET_ methods for non-primary key fields.
Step 4: Activate the Class. 

Upon activation, dependent classes will get activated and SAP generates essential base agent methods:

  1. CREATE_PERSISTENT( ) – Creates a new persistent object.
  2. DELETE_PERSISTENT( ) – Deletes an existing object.
  3. GET_PERSISTENT( ) – Retrieves an object from the database.
Step 5: How to Use the Persistence Class in ABAP

To interact with a persistent object in SE38 Report(Driver Pgm), we need to access the methods defined in the Base Agent Class (e.g., ZCB_ZAK_PERSISTENCE). However, there are some limitations:

  1. Base Agent Class is Abstract: The Base Agent Class cannot be instantiated directly because it is abstract. It provides foundational methods but cannot be used to create objects on its own.

  2. Actor Class Inherits Base Agent Class: The Actor/Agent Class (e.g., ZCA_ZAK_PERSISTENCE) inherits from the Base Agent Class, so it contains all the persistence-related methods. However, the Actor Class is private and cannot be accessed directly outside of its scope.

  3. Accessing the Actor Class via the Static AGENT Attribute: The Actor Class provides a static, read-only attribute called AGENT. This attribute acts as a singleton instance of the Actor Class. By accessing this attribute, we can interact with the persistence methods ( such as create_persistance(), get_persistance(), Delete_persistance() ) without needing to instantiate the class directly.

In summary, while the Base Agent Class and the Actor Class are not directly accessible, you can interact with the persistence functionality through the static AGENT attribute of the Actor Class, which ensures that only one instance of the Actor Class exists and provides access to all persistence methods.


Driver Pgm:

*&---------------------------------------------------------------------*
*& Report YAK_OOP_PERSISTANCE_DRIVER_PGM
*&---------------------------------------------------------------------*
REPORT yak_oop_persistance_driver_pgm.

* Selection Screen Block 1 - Input fields for Employee Data
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME.
PARAMETERS:
  p_eid   
TYPE zak_emp-zak_empid,      " Employee ID
  p_ename 
TYPE zak_emp-zak_empname,    " Employee Name
  p_edesig
TYPE zak_emp-zak_empdesig.   " Employee Designation
SELECTION-SCREEN END OF BLOCK b1.

* Selection Screen Block 2 - Radio buttons for CRUD operations
SELECTION-SCREEN BEGIN OF BLOCK b2 WITH FRAME.
PARAMETERS:
  p_r1
RADIOBUTTON GROUP gp1 USER-COMMAND fc1,  " Create Record
  p_r2
RADIOBUTTON GROUP gp1 DEFAULT 'X',      " Read Record
  p_r3
RADIOBUTTON GROUP gp1,                  " Update Record
  p_r4
RADIOBUTTON GROUP gp1.                  " Delete Record
SELECTION-SCREEN END OF BLOCK b2.

* Declare object references for Persistence and Actor classes
DATA: obj_actor TYPE REF TO zca_zak_persistance,
      obj_pers 
TYPE REF TO zcl_zak_persistance.

* Initialization block - Assign agent class reference
INITIALIZATION.
  obj_actor
= zca_zak_persistance=>agent.

* Event: Trigger actions based on radio button selection
AT SELECTION-SCREEN ON RADIOBUTTON GROUP gp1.
 
CASE sy-ucomm.
   
WHEN 'FC1'.
     
IF p_r1 = 'X'.
       
PERFORM create_record.  " Call Create Record Subroutine
     
ELSEIF p_r2 = 'X'.
       
PERFORM read_record.    " Call Read Record Subroutine
     
ELSEIF p_r3 = 'X'.
       
PERFORM update_record.  " Call Update Record Subroutine
     
ELSEIF p_r4 = 'X'.
       
PERFORM delete_record.  " Call Delete Record Subroutine
     
ENDIF.
 
ENDCASE.

*&---------------------------------------------------------------------*
*& Form GET_PERSISTENT_OBJECT - Fetch persistent object (Refactored)
*&---------------------------------------------------------------------*
FORM get_persistent_object USING p_empid TYPE zakempid  CHANGING p_obj TYPE REF TO zcl_zak_persistance.
 
TRY.
      p_obj
= obj_actor->get_persistent( p_empid ).
   
CATCH cx_os_object_not_found.
*      p_obj = NULL.
 
ENDTRY.
ENDFORM.

*&---------------------------------------------------------------------*
*& Form CREATE_RECORD - Creates a new Employee Record
*&---------------------------------------------------------------------*
FORM create_record.
  obj_pers
= obj_actor->create_persistent( p_eid ).

 
IF obj_pers IS BOUND.
    obj_pers
->set_zak_empname( p_ename ).
    obj_pers
->set_zak_empdesig( p_edesig ).
   
COMMIT WORK.
   
MESSAGE 'Record Created Successfully' TYPE 'I'.
 
ELSE.
   
MESSAGE 'Failed to Create Record' TYPE 'E'.
 
ENDIF.
ENDFORM.

*&---------------------------------------------------------------------*
*& Form READ_RECORD - Reads an Employee Record
*&---------------------------------------------------------------------*
FORM read_record.
 
PERFORM get_persistent_object USING p_eid CHANGING obj_pers.

 
IF obj_pers IS BOUND.
   
MESSAGE |Employee ID: { obj_pers->get_zak_empid( ) } Name: { obj_pers->get_zak_empname( ) } Designation: { obj_pers->get_zak_empdesig( ) }| TYPE 'I'.
 
ELSE.
   
MESSAGE 'Employee record not found' TYPE 'E'.
 
ENDIF.
ENDFORM.

*&---------------------------------------------------------------------*
*& Form UPDATE_RECORD - Updates an Employee Record
*&---------------------------------------------------------------------*
FORM update_record.
 
PERFORM get_persistent_object USING p_eid CHANGING obj_pers.

 
IF obj_pers IS BOUND.
    obj_pers
->set_zak_empname( p_ename ).
    obj_pers
->set_zak_empdesig( p_edesig ).
   
COMMIT WORK.
   
MESSAGE 'Record Updated Successfully' TYPE 'I'.
 
ELSE.
   
MESSAGE 'Record Not Found' TYPE 'E'.
 
ENDIF.
ENDFORM.

*&---------------------------------------------------------------------*
*& Form DELETE_RECORD - Deletes an Employee Record
*&---------------------------------------------------------------------*
FORM delete_record.
 
PERFORM get_persistent_object USING p_eid CHANGING obj_pers.

 
IF obj_pers IS BOUND.
    obj_actor
->delete_persistent( p_eid ).
   
COMMIT WORK.
   
MESSAGE 'Record Deleted Successfully' TYPE 'I'.
 
ELSE.
   
MESSAGE 'Record Not Found' TYPE 'E'.
 
ENDIF.
ENDFORM.
































































Monday, March 17, 2025

Day 2 - Global Class and OOPs Features

 






1.Global Class:


  1. All the features we saw in the previous post regarding local class and components of class, objects are applicable to global class as well. 
  2. However, unlike local classes, a global class is defined at the global level and can be accessed across various programs, function groups, or function modules within the SAP system.
  3. Global classes can be created using SE24 (ABAP Workbench). 
  4. The naming convention for global classes is ZCL<class_name>.
  5. It is possible to convert a local class into a global class, but the reverse — converting a global class into a local class — is not allowed.

  • SE24 → Object Type → Import → Local Classes in the Program
  • Enter the program name → preferred global class name
  • Click Import, then Save the class and Activate it.
  • Global Class Example:

    In this global class we will see method returning multiple exporting parameter. The same can also be done using local class.

                

    Report Program:


    REPORT yak_global_class_pgm.

    INITIALIZATION.

    PARAMETERs p_cust TYPE kna1-kunnr.

    DATA: lv_name1 TYPE kna1-name1,
          lv_ort01 TYPE kna1-ort01.

    START-OF-SELECTION.

    DATA: obj TYPE REF TO yak_global.
    CREATE OBJECT obj.

    CALL METHOD obj->m1
      EXPORTING
        kunnr = p_cust
      IMPORTING
        name1 = lv_name1
        ort01 = lv_ort01.

    WRITE: lv_name1, lv_ort01.


    2.How to call a method inside a method and "ME" Keyword.

    1. Below code demonstrates the concept of calling a method within another method in ABAP Object-Oriented Programming (OOP) and how a public method can access protected attributes and protected methods.
    2. The ME keyword represents the current calling object. 

    *&-------------------------------------------------------------------
    *& Report YAK_OOP_METHOD
    *&-------------------------------------------------------------------
    REPORT yak_oop_method.

    CLASS lcl_demo_method DEFINITION.

     
    PUBLIC SECTION.
       
    METHODS set IMPORTING empid   TYPE i
                              empname
    TYPE c OPTIONAL.

     
    PROTECTED SECTION.
       
    DATA: lv_empid       TYPE i,
              lv_empname
    (20) TYPE c.
       
    METHODS: display.

    ENDCLASS.

    CLASS lcl_demo_method IMPLEMENTATION.

     
    METHOD set.
        lv_empid
    = empid.    " Assigning parameter to protected attribute
        lv_empname
    = empname." Assigning parameter to protected attribute

       
    CALL METHOD me->display. " Calling the protected method 'display'
     
    ENDMETHOD.

     
    METHOD display.
       
    WRITE: / 'Employee ID:', lv_empid,
               /
    'Employee Name:', lv_empname
     
    ENDMETHOD.

    ENDCLASS.

    START-OF-SELECTION.

     
    DATA: obj TYPE REF TO lcl_demo_method.
     
    CREATE OBJECT obj. " Creating object of lcl_demo_method


     
    CALL METHOD obj->set  " Calling 'set' method with employee details
       
    EXPORTING
          empid  
    = 100456
          empname
    = 'SAP DEV'.


    Output of the Program:
    Employee ID: 100456 Employee Name: SAP DEV

    3.Structure and Internal Tables in Class

    Requirement: object-oriented approach to retrieving and displaying customer data based on a specified country (land1).

    *&-------------------------------------------------------------------
    *& Report YAK_OOP_METHOD1
    *&-------------------------------------------------------------------
    REPORT yak_oop_method1.

    CLASS lcl_customers DEFINITION.


     
    PUBLIC SECTION.

        METHODS get_customer IMPORTING land1 TYPE land1.

     
    PROTECTED SECTION.

        TYPES: BEGIN OF ty_cust,
                 kunnr
    TYPE kna1-kunnr,
                 land1
    TYPE land1,
                 name1
    TYPE name1,
                 ort01
    TYPE ort01,
              
    END OF ty_cust.

       
    DATA: it_cust TYPE STANDARD TABLE OF ty_cust,
              wa_cust
    TYPE ty_cust.


       
    METHODS display.
    ENDCLASS.


    CLASS lcl_customers IMPLEMENTATION.
      

     
    METHOD get_customer.
       
    SELECT kunnr, land1, name1, ort01
         
    FROM kna1
         
    INTO TABLE @it_cust
         
    WHERE land1 = @land1.

       
    IF sy-subrc EQ 0.
         
    CALL METHOD me->display.
       
    ENDIF.
     
    ENDMETHOD.

     
    METHOD display.
       
    LOOP AT it_cust INTO wa_cust.
         
    WRITE:/ wa_cust-kunnr,
                 wa_cust
    -land1,
                 wa_cust
    -name1,
                 wa_cust
    -ort01.
       
    ENDLOOP.
     
    ENDMETHOD.
    ENDCLASS.

    START-OF-SELECTION.

     
    PARAMETERS p_land1 TYPE kna1-land1.

     
    DATA: ob TYPE REF TO lcl_customers.
     
    CREATE OBJECT ob.

     
    CALL METHOD ob->get_customer
       
    EXPORTING
          land1
    = p_land1.

    4. FRIEND Class, DEFFER Keyword:

    1. In general, the protected and private components of a class cannot be accessed outside the class. However, in certain cases, there may be a business requirement to access these components. 
    2. This can be achieved using the FRIEND class feature in Object-Oriented Programming (OOP), which allows specific classes to access all components of another class, regardless of their visibility section (protected or private).
    3. The DEFFER keyword is used to inform the system that the class is declared later in the program, rather than at the beginning.
    Real-World Uses of Friend Classes

    1. Debugging Tools

    A class that implements a debugging tool can be declared as a friend of the class it is debugging. This allows the debugger to access private and protected members of the target class, which helps in inspecting internal states and diagnosing issues more effectively.

    2. Factory Pattern Implementation

    In scenarios where the Factory Design Pattern is used, the factory class can be made a friend of the classes it instantiates. This allows the factory to access constructors or initialization logic that is otherwise private or protected, thus controlling object creation while maintaining encapsulation.

    3. Unit Testing Frameworks

    A unit testing class or framework can be granted friendship by the class being tested. This setup is especially useful when you need to test private or protected members directly, which would otherwise be inaccessible through normal public interfaces.

     Example:

    *&-------------------------------------------------------------------
    *& Report YAK_OOP_FRIEND
    *&-------------------------------------------------------------------
    REPORT yak_oop_friend.

    " Declare class lcl_friend later in the program using DEFERRED
    CLASS lcl_friend DEFINITION DEFERRED.

    " Declare class lcl_class and specify that lcl_friend is a FRIEND class
    CLASS lcl_class DEFINITION FRIENDS lcl_friend.
     
    PUBLIC SECTION.
       
    METHODS m1.  " Public method
     
    PROTECTED SECTION.
       
    METHODS m2.  " Protected method
     
    PRIVATE SECTION.
       
    METHODS m3.  " Private method
    ENDCLASS.

    " Implement methods of class lcl_class
    CLASS lcl_class IMPLEMENTATION.
     
    METHOD m1.
       
    WRITE:/ 'Public Section Method m1'.
     
    ENDMETHOD.
     
    METHOD m2.
       
    WRITE:/ 'Protected Section Method m2'.
     
    ENDMETHOD.
     
    METHOD m3.
       
    WRITE:/ 'Private section method m3'.
     
    ENDMETHOD.
    ENDCLASS.

    " Define class lcl_friend and implement its method
    CLASS lcl_friend DEFINITION.
     
    PUBLIC SECTION.
       
    METHODS mf.  " Friend class method
    ENDCLASS.

    CLASS lcl_friend IMPLEMENTATION.
     
    METHOD mf.
       
    WRITE:/ 'Friend class method'.

       
    " Create an instance of lcl_class
       
    DATA: lcl_obj TYPE REF TO lcl_class.
       
    CREATE OBJECT lcl_obj.

       
    " Call methods of lcl_class
       
    CALL METHOD lcl_obj->m1. " Public method
       
    CALL METHOD lcl_obj->m2. " Protected method (accessible due to FRIEND relationship)
       
    CALL METHOD lcl_obj->m3. " Private method (accessible due to FRIEND relationship)
     
    ENDMETHOD.
    ENDCLASS.

    " Main program execution
    START-OF-SELECTION.

     
    " Create an instance of the friend class lcl_friend
     
    DATA: f_obj TYPE REF TO lcl_friend.
     
    CREATE OBJECT f_obj.

     
    " Call the method of the friend class
     
    CALL METHOD f_obj->mf.


    5.Inheritance:

    1. In Object-Oriented Programming (OOP), inheritance allows one class to access the components (methods and attributes) of another class. It enables the reuse and extension of functionality from one class into another.
    2. The class from which components are inherited is called the superclass or base class, while the class that inherits the components is referred to as the subclass or derived class.

    3. Inheritance in OOP supports the inheritance of public and protected components of the base class. However, private components of the base class cannot be inherited by a subclass.
    4. In ABAP, the INHERITING FROM keyword is used as part of the class definition in the subclass to achieve inheritance.
      CLASS subclass DEFINITION INHERITING FROM superclass. " Subclass definition here ENDCLASS.
    5. REDEFINE keyword is used to override or redefine a method of a parent class in a subclass.This allows you to modify or extend the behavior of the method in the subclass.
    6. SUPER Keyword used to call the parent class method implementation in sub class.
    7. Final is the keyword using which we can restrict the class to be inherited.ie.. if the class has final then it cannot be inherited.

    Types of Inheritance:

      1. Single Inheritance: A subclass inherits from a single superclass.
      2. Multiple Inheritance: A subclass inherits from more than one superclass.
      3. Multilevel Inheritance: A subclass inherits from a superclass, and that superclass itself is derived from another class.

    Simple Example:

    The provided program demonstrates single inheritance and multilevel inheritance using ABAP classes.
    1. Single Inheritance: In the example, the lcl_cycle class inherits from the lcl_vehicle class. This is an example of single inheritance
    2. Multilevel Inheritance:The lcl_car class is an example of multilevel inheritance, where lcl_car inherits from lcl_cycle, and lcl_cycle itself inherits from lcl_vehicle. This creates a chain of inheritance, where lcl_car indirectly inherits from lcl_vehicle through lcl_cycle.
    Key Components:
    • lcl_vehicle: This is the base class (parent class) with properties like wheels and color, and a method display.
    • lcl_cycle: This is a subclass of lcl_vehicle and adds additional functionality, like setcycle and the break property.
    • lcl_car: This is a subclass of lcl_cycle and overrides the display method while adding additional functionality, such as the gears property.

    *&-------------------------------------------------------------------
    *& Report YAK_OOP_INHERITANCE
    *&-------------------------------------------------------------------

    REPORT yak_oop_inheritance.

    " Base class for vehicles
    CLASS lcl_vehicle DEFINITION.
     
    PUBLIC SECTION.
       
    METHODS display.
     
    PROTECTED SECTION.
       
    DATA: wheels    TYPE i,
             
    color(10) TYPE c. " Parameters
    ENDCLASS.

    CLASS lcl_vehicle IMPLEMENTATION.
     
    METHOD display.
       
    WRITE: wheels, color. " Display wheels and color of the vehicle
     
    ENDMETHOD.
    ENDCLASS.

    " Derived class for cycles inheriting from lcl_vehicle
    CLASS lcl_cycle DEFINITION INHERITING FROM lcl_vehicle.
     
    PUBLIC SECTION.
       
    METHODS setcycle.
     
    PROTECTED SECTION.
       
    DATA: break TYPE i. " Property for break count in cycles
    ENDCLASS.

    CLASS lcl_cycle IMPLEMENTATION.

     
    METHOD setcycle.
        wheels
    = 2. " Cycles have 2 wheels
       
    color = 'RED'. " Cycles are RED by default
        break
    = 2. " Cycles have 2 breaks
     
    ENDMETHOD.
    ENDCLASS.

    " Derived class for cars inheriting from lcl_cycle
    CLASS lcl_car DEFINITION INHERITING FROM lcl_cycle.
     
    PUBLIC SECTION.
       
    METHODS setcar.
       
    METHODS display REDEFINITION. " Method override to change the display output
     
    PROTECTED SECTION.
       
    DATA: gears TYPE i. " Property for gears in the car
    ENDCLASS.

    CLASS lcl_car IMPLEMENTATION.
     
    METHOD setcar.
        wheels
    = 4. " Cars have 4 wheels
       
    color = 'SILVER'. " Cars are SILVER by default
        break
    = 1. " Cars have 1 break (for simplicity in this example)
        gears
    = 5. " Cars have 5 gears
     
    ENDMETHOD.

     
    METHOD display.

        CALL METHOD super->display. "Calling Parent class Implementation

        WRITE: / break, gears. " Override display to include gears information
     
    ENDMETHOD.
    ENDCLASS.

    START-OF-SELECTION.
     
    " Create an object for lcl_cycle and call methods
     
    DATA: ob TYPE REF TO lcl_cycle.
     
    CREATE OBJECT ob.
     
    CALL METHOD ob->setcycle.
     
    CALL METHOD ob->display.

     
    " Create an object for lcl_car and call methods
     
    DATA: ob_car TYPE REF TO lcl_car.
     
    CREATE OBJECT ob_car.
     
    CALL METHOD ob_car->setcar.
     
    CALL METHOD ob_car->display.


    6.Final Keyword:

    In ABAP, you can use the FINAL keyword to restrict a class from being inherited. When a class is declared as FINAL, it cannot be further subclassed, meaning no class can inherit from it.

    Here’s how the FINAL keyword works:

    Example of a FINAL class:
    CLASS lcl_final_class DEFINITION FINAL. PUBLIC SECTION. METHODS display. PROTECTED SECTION. DATA: wheels TYPE i, color TYPE c LENGTH 10. ENDCLASS. CLASS lcl_final_class IMPLEMENTATION. METHOD display. WRITE: / 'This is a final class.'. ENDMETHOD. ENDCLASS.
    Trying to Inherit from a FINAL class:
    CLASS lcl_inherited_class DEFINITION INHERITING FROM lcl_final_class. PUBLIC SECTION. METHODS display. ENDCLASS.
    Error:

    In the above case, you would get an error at compile time saying:

    • "The class lcl_final_class is declared as FINAL, so it cannot be inherited."
    7.Method Overriding:

    When a subclass provides a new implementation for a method that is already defined in its superclass, this is called method overriding. The subclass redefines the behavior of the parent class method.
    1. REDEFINE Keyword:
      In ABAP, the REDEFINE keyword is used in the subclass to override a method inherited from the superclass. This allows the subclass to provide its own implementation of the method.

    2. Visibility/Method Type:
      When you override a method in a subclass, the visibility (such as PUBLIC, PROTECTED, or PRIVATE) and method type (such as instance method or static method) of the parent class method cannot be changed.

      • Only PUBLIC and PROTECTED methods from the superclass can be redefined in the subclass.
      • Private methods cannot be redefined.
    3. Using the SUPER Keyword:
      If you want to call the method of the superclass from within the redefined method of the subclass, you use the SUPER keyword. This allows you to call the original method implementation from the parent class in addition to the new functionality defined in the subclass.

    4. Static Methods:
      Static methods (methods defined with the CLASS-METHODS keyword) cannot be redefined in the subclass. Only instance methods (methods defined with METHODS) can be overridden.

    8. Abstract Class in ABAP

    1. A class that contains at least one abstract method is called an abstract class. An abstract method is a method that is declared but not implemented in the class. 
    2. We declare a method as abstract when we do not know its implementation details yet. The actual implementation of the abstract method is provided in the subclass.
    3. Abstract methods are declared using the ABSTRACT keyword. If a class contains at least one abstract method, the class itself must also be declared as abstract
    4. Abstract methods should be declared in the public or protected section of the class. They are also referred to as non-concrete methods.
    5. Static methods and constructors cannot be declared as abstract because they cannot be redefined in a subclass.
    6. Any subclass that inherits from an abstract class must implement all of the abstract methods of the superclass. If a subclass does not implement all abstract methods, it too must be declared as abstract.
    7. Abstract classes cannot be instantiated directly because they are incomplete. However, once the abstract methods are implemented in the subclass, we can create an object of the subclass.
    8. Assigning a subclass object to a reference of the abstract superclass is known as narrow casting. For example, <Abs_spr_cls_ref> = <Obj_sub_cls>.
    9. Narrow casting refers to the process of assigning a more specific object (subclass) to a reference of a more general type (abstract superclass), essentially switching from a more detailed view to a less detailed one
    10. When narrow casting is done, the reference variable can access only the methods of the superclass. To access methods specific to the subclass, we need to use dynamic method callsCALL METHOD <Abs_spr_cls_ref>->('<sub_cls_name>').

    Syntax Example:

    1. CLASS lcl_abstract_example DEFINITION ABSTRACT. PUBLIC SECTION. METHODS: display ABSTRACT. "Abstract method without implementation ENDCLASS.
    2. CLASS lcl_car DEFINITION INHERITING FROM lcl_abstract_example. PUBLIC SECTION. METHODS: display REDEFINITION. "Implementing the abstract method ENDCLASS. CLASS lcl_car IMPLEMENTATION. METHOD display. WRITE: 'This is a car'. ENDMETHOD. ENDCLASS.
    3. DATA: obj_car TYPE REF TO lcl_car, obj_vehicle TYPE REF TO lcl_abstract_example. CREATE OBJECT obj_car. obj_vehicle = obj_car. "Narrow casting
    Example:

    *&------------------------------------------------------------------
    *& Report YAK_OOP_ABSTRACT
    *&------------------------------------------------------------------
    REPORT yak_oop_abstract.

    CLASS lcl_restaurant DEFINITION ABSTRACT.
      PUBLIC SECTION.
        METHODS : store,
                 display,
                 payment ABSTRACT.
      PROTECTED SECTION.
        DATA : tableno TYPE i,
               steward TYPE string.
    ENDCLASS.

    CLASS lcl_restaurant IMPLEMENTATION.

      METHOD store.
        tableno = 3.
        steward = 'ABC'.
      ENDMETHOD.

      METHOD display.
        WRITE :/ tableno, steward.
      ENDMETHOD.

    ENDCLASS.

    CLASS lcl_cheque DEFINITION INHERITING FROM lcl_restaurant.
      PUBLIC SECTION.
        METHODS payment REDEFINITION.
        METHODS m1.
      PROTECTED SECTION.
        DATA : cqno TYPE i,
               cqdate TYPE d,
               cqamt TYPE i.
    ENDCLASS.

    CLASS lcl_cheque IMPLEMENTATION.

      METHOD payment.
        cqno = 123.
        cqdate = sy-datum.
        cqamt = 455.
        WRITE :/ 'Details of Cheque:', cqno, cqdate, cqamt.
      ENDMETHOD.

      METHOD m1.
        WRITE :/ 'Inside direct method m1 of cheque class'.
      ENDMETHOD.

    ENDCLASS.

    CLASS lcl_creditcard DEFINITION INHERITING FROM lcl_restaurant.
      PUBLIC SECTION.
        METHODS payment REDEFINITION.
      PROTECTED SECTION.
        DATA : ccno TYPE i,
               ccexpdate TYPE d,
               ccamt TYPE i.
    ENDCLASS.

    CLASS lcl_creditcard IMPLEMENTATION.

      METHOD payment.
        ccno = 455.
        ccexpdate = sy-datum.
        ccamt = 234.
        WRITE :/ 'Credit card details:', ccno, ccexpdate, ccamt.
      ENDMETHOD.

    ENDCLASS.

    START-OF-SELECTION.
      DATA r TYPE REF TO lcl_restaurant.
    * Create object r. "syntax error

      DATA cq TYPE REF TO lcl_cheque.
      CREATE OBJECT cq.

      FORMAT COLOR 3.
      WRITE :/ 'Using Cheque class object'.
      CALL METHOD : cq->store,
                    cq->display,
                    cq->payment,
                    cq->m1.

      r = cq. "Narrow casting
      FORMAT COLOR 7.
      WRITE :/ 'Cheque class object assigned to restaurant'.
      CALL METHOD : r->store,
                    r->display,
                    r->payment.
    * r->m1. "syntax error

      " Dynamic method call to access m1 method of the subclass
      CALL METHOD r->('M1').

      ULINE.
      FORMAT COLOR 1.
      WRITE :/ 'CREDIT CARD Object....'.
      DATA cc TYPE REF TO lcl_creditcard.
      CREATE OBJECT cc.

      CALL METHOD : cc->store,
                    cc->display,
                    cc->payment.

      r = cc. "Narrow casting
      FORMAT COLOR 2.
      WRITE :/ 'Credit card class object assigned to restaurant'.
      CALL METHOD : r->store,
                    r->display,
                    r->payment.


    9.Interface
    1. Pure Abstract Class:
      An interface in ABAP is often referred to as a "pure abstract class." This means that all methods defined within an interface are abstract by default. Interfaces do not contain any method implementations, only method declarations.

    2. Public Visibility:
      Interface components, such as constants and methods, are public by default. An interface does not have an explicit visibility section like a normal class. Therefore, any method or constant declared in an interface is automatically public and accessible to classes that implement the interface.

    3. No Method Implementations:
      Interfaces cannot contain method implementations. They only contain method declarations. The responsibility for providing the method implementation lies with the class that implements the interface.

    4. Implementing an Interface:
      If a class wants to implement an interface (whether local or global), it must declare the interface in the public section of the class using the INTERFACES keyword.
      The class must also implement all the methods declared in the interface.

      • If the class does not implement all the methods, those methods should be flagged as abstract and the class should be considered an abstract class. Otherwise system will throw syntax error.

      • The abstract class must then be inherited by a subclass, which must redefine and provide implementations for the abstract methods. So that we can access those methods using subclass objects, otherwise we cant. Pls refer the example 2 for more clarity.

    5. Implementation Class:
      A class that implements an interface is called the implementation class. This class provides the concrete implementations of the all the methods declared in the interface.

    6. Interfaces must in the Public Section:
      When implementing an interface, the interface must be declared in the public section of the local class. This ensures that the methods of the interface are accessible from outside the class.

    7. Multiple Inheritance:
      Interfaces allow for multiple inheritance. A single class can implement multiple interfaces, which means it can inherit method declarations from multiple sources. This is one of the main advantages of using interfaces in object-oriented programming.

    8. Prefixing Interface Methods:
      When referring to a method of an interface outside the context of the interface, the method must be prefixed with the name of the interface, followed by a tilde (~).

      <interface_name>~<method_name>

      This ensures that you are calling the method of the correct interface.

    9. Aliases Name for Interface component:
      Aliases are alternative names for interface components, improving readability and reducing the need for long naming conventions.
    10. No Constructors in Interfaces :
      Interfaces cannot contain constructors. Constructors are specific to classes, and since interfaces do not contain any implementation, they do not define any constructor logic.

    11. Interface Inheritance:

      • In ABAP, an interface can include other interfaces. When a class implements an interface that has included interfaces, the class must implement all the methods from the parent interface as well as any methods from the included interfaces.
      • This means that if an interface inherits methods from other interfaces (whether directly or indirectly), the class implementing the main interface is required to implement all methods from all inherited interfaces, not just those defined in the immediate interface.
    12. Global Classes Interfaces:
      If a global class needs to implement one or more global interfaces, it must declare those interfaces in the INTERFACES tab.

    Example 1 -  Class redefined all the Interface Methods:

    The Below ABAP code you demonstrates the concept of interfaces, multiple inheritance, and narrow casting. Here, I have implemented a local interface and a local implementation class. This can also be achieved using a global interface, a global implementation class, and a driver program.

    Key Concepts:
    1. Interfaces: if_rectangle and if_square are interfaces that define common methods (area and perimeter) and constants (such as length, breadth, and side).
    2. Multiple Inheritance: The class lcl_if implements both interfaces if_rectangle and if_square.
    3. Narrow Casting: An object of class lcl_if is cast into references of the interfaces if_rectangle and if_square to demonstrate how the methods of the interfaces can be called from the interface references.

    *&----------------------------------------------------------------
    *& Report YAK_OOP_INTERFACE
    *&----------------------------------------------------------------
    REPORT yak_oop_interface.

    INTERFACE if_rectangle.
      " In Interface By Default, all components are public
      CONSTANTS: length  TYPE i VALUE 10,
                 breadth TYPE i VALUE 5.
      METHODS: area,
        perimeter.
    ENDINTERFACE.

    INTERFACE if_square.
      CONSTANTS: side TYPE i VALUE 10.
      METHODS: area,
        perimeter.
    ENDINTERFACE.

    CLASS lcl_if DEFINITION.
      PUBLIC SECTION.
        INTERFACES: if_rectangle,
          if_square.
      PROTECTED SECTION.
        DATA: res TYPE i.
    ENDCLASS.

    CLASS lcl_if IMPLEMENTATION.

      METHOD if_rectangle~area.
        WRITE: / 'This is from the interface rectangle - area method'.
      ENDMETHOD.

      METHOD if_rectangle~perimeter.
        WRITE: / 'This is from the interface rectangle - perimeter method'.
      ENDMETHOD.

      METHOD if_square~area.
        WRITE: / 'This is from the interface square - area method'.
      ENDMETHOD.

      METHOD if_square~perimeter.
        WRITE: / 'This is from the interface square - perimeter method'.
      ENDMETHOD.

    ENDCLASS.

    START-OF-SELECTION.

      DATA: ob TYPE REF TO lcl_if.
      CREATE OBJECT ob.

      NEW-LINE.
      WRITE: / 'From class object'.
      CALL METHOD: ob->if_rectangle~area,
                   ob->if_rectangle~perimeter,
                   ob->if_square~area,
                   ob->if_square~perimeter.

      DATA: if_ref_rec TYPE REF TO if_rectangle.
      DATA: if_ref_sq TYPE REF TO if_square.

      " Narrow Casting: Assigning object reference to interface reference
      if_ref_rec = ob.  " Narrow Casting for if_rectangle

      NEW-LINE.
      WRITE: / 'From interface rectangle reference'.
      CALL METHOD: if_ref_rec->area,
                   if_ref_rec->perimeter.

      if_ref_sq = ob.  " Narrow Casting for if_square

      NEW-LINE.
      WRITE: / 'From interface square reference'.
      CALL METHOD: if_ref_sq->area,
                   if_ref_sq->perimeter.


    Output Example:

    From class object This is from the interface rectangle - area method This is from the interface rectangle - perimeter method This is from the interface square - area method This is from the interface square - perimeter method From interface rectangle reference This is from the interface rectangle - area method This is from the interface rectangle - perimeter method From interface square reference This is from the interface square - area method This is from the interface square - perimeter method
    Example 2 -  Class not redefiing all the Interface Methods:
    1. Interface Definition:

      • The interface if_part_impl defines three methods: m1, m2, and m3.
    2. Abstract Class lcl_part_impl:

      • The class lcl_part_impl is declared as abstract and partially implements the interface.
      • Only the m1 method is implemented in lcl_part_impl, and methods m2 and m3 are marked as abstract in the class definition (ABSTRACT METHODS m2 m3).
    3. Subclass Implementation lcl_sub_class:

      • The subclass lcl_sub_class inherits from lcl_part_impl and provides implementations for the abstract methods m2 and m3 that were left unimplemented in the parent class.
      • The methods m2 and m3 are redefined in the subclass using the REDEFINITION keyword.
    4. Main Program:

      • An instance of the subclass lcl_sub_class is created, and the interface methods (m1, m2, and m3) are called.
      • The m1 method is executed from the abstract class, while m2 and m3 are executed from the subclass.

    *&-----------------------------------------------------------------
    *& Report YAK_OOP_INTERFACE_PART_IMPL
    *&-----------------------------------------------------------------
    REPORT yak_oop_interface_part_impl.

    INTERFACE if_part_impl.
     
    METHODS: m1,
        m2
    ,
        m3
    .
    ENDINTERFACE.

    "Class partially Implements Interface Methods
    CLASS lcl_part_impl DEFINITION ABSTRACT.
     
    PUBLIC SECTION.
       
    INTERFACES: if_part_impl ABSTRACT METHODS m2 m3.
    ENDCLASS.

    CLASS lcl_part_impl IMPLEMENTATION.
     
    METHOD if_part_impl~m1.
       
    WRITE: / 'Implementing interface method m1 by patial impl class'.
     
    ENDMETHOD.
    ENDCLASS.

    *START-OF-SELECTION.

    "Instances of the abstract class "LCL_PART_IMPL" cannot be generated. -
    *data: ob_part_impl TYPE REF TO lcl_part_impl.
    *create OBJECT ob_part_impl.

    CLASS lcl_sub_class DEFINITION INHERITING FROM lcl_part_impl.
     
    PUBLIC SECTION.
       
    METHODS: if_part_impl~m2 REDEFINITION,
          if_part_impl
    ~m3 REDEFINITION.

    ENDCLASS.


    CLASS lcl_sub_class IMPLEMENTATION.
     
    METHOD if_part_impl~m2.
       
    WRITE:/ 'Implementing interface method m1 by subclass'.
     
    ENDMETHOD.

     
    METHOD if_part_impl~m3.
       
    WRITE:/ 'Implementing interface method m2 by subclass'.
     
    ENDMETHOD.
    ENDCLASS.

    START-OF-SELECTION.

     
    DATA: ob_sub_class TYPE REF TO lcl_sub_class.
     
    CREATE OBJECT ob_sub_class.

     
    "Calling methods using sub class obj
     
    CALL METHOD: ob_sub_class->if_part_impl~m1,
      ob_sub_class
    ->if_part_impl~m2,
      ob_sub_class
    ->if_part_impl~m3.


    Output:
    Implementing interface method m1 in the partial implementation class Implementing interface method m2 in subclass Implementing interface method m3 in subclass


    Example3 - Aliases Name for Interface component:

    Aliases are alternative names for interface components, improving readability and reducing the need for long naming conventions.

    INTERFACE zif_vehicle. METHODS start_engine. ENDINTERFACE. CLASS zcl_car DEFINITION. PUBLIC SECTION. INTERFACES zif_vehicle. ALIASES ignite FOR zif_vehicle~start_engine. " Alias for method ENDCLASS. CLASS zcl_car IMPLEMENTATION. METHOD ignite.         " Using alias instead of zif_vehicle~start_engine
    WRITE: 'Engine started'. ENDMETHOD. ENDCLASS. START-OF-SELECTION. DATA: lo_car TYPE REF TO zcl_car. CREATE OBJECT lo_car. lo_car->ignite.       " Using alias instead of zif_vehicle~start_engine



    Day 3 - Persistence Service

      DAY 1 - Introduction - OOPs Concept, Local Class and Class Components Day 2 - Global Class and OOPs Features 1.Persistence Service: In SAP...