Skip to Content

In my OO Programming with ABAP Objects: Encapsulation blog entry, we continued our discussion on OOP by showing how visibility sections could be used to hide implementation details of a class. If you are new to OOP, you might be wondering why you would want to go to such lengths to encapsulate your code. After all, don’t we want our software to be open these days? However, the use of implementation hiding techniques does not imply that software must be closed off completely. Rather, we just want to establish some healthy boundaries so that we can give the software some structure. This structure helps the software to gracefully adapt to inevitable changes within a particular area without affecting the overall integrity of the software as a whole.

In this blog entry, I will introduce another core concept of OOP called inheritance. Inheritance describes a relationship between related classes within a particular problem domain. Here, you will see that the use of good encapsulation techniques enables you to expand and enhance the functionality of your applications without having to modify pre-existing classes. In my next blog entry, we will see how these relationships can be exploited using polymorphism.

Generalization and Specialization

During the Object-Oriented Analysis & Design (or OOAD) process, we evaulate real world phenomena and try to simulate the problem domain using classes of objects. Frequently, this classification process goes through several iterations before we get it right. For instance, our first pass through the requirements might generate an OO design with some very basic classes. As we dig deeper, we focus in on determining the roles and responsibilities of each class. Along the way, our classes evolve to become more specialized.

In an ideal world, this analysis process would take place in a vaccuum, allowing us to completely refine our object model before we implement it. Unfortunately, most of us do not have this luxury as we are subject to tight deadlines and limited budgets. Typically, we must draw a line in the sand and build the best software we can given the constraints laid before us. In the past, such hasty development has made it very difficult to adapt the software to implement new functionality, etc. Here, developers would have to decide whether or not they felt like an enhancement could be implemented without jeopardizing the existing production code. If the answer to that question was no, they were forced to cut their losses and try to salvage as much of the code as they could using the “copy-and-paste” approach to building new development objects. Both of these approaches are fraught with risks. Early object-oriented researches recognized that there had to be a better way to extending software.

When you think about it, an enhancement extends or specializes a portion of the system in some way. In an OO system, this implies that we want to enhance or extend certain functionality within one or more classes. Here, we don’t really want to modify the existing class(es). Rather, we just want to expand then to handle more specialized requirements, etc. One way to implement this kind of specialization in object-oriented languages is through inheritance.

Inheritance defines a relationship between two classes; the original class is called the superclass (or parent class) and the extended class is called the subclass (or child class). In an inheritance relationship, a subclass inherits the components from its superclass (e.g. attributes, methods, etc.). Subclasses can then build on these existing components to implement additional functionality. When thinking about inheritance, it is important to realize that the relationship is not transient in nature. In other words, a subclass is not just a copy or clone of its superclass. For instance, if you change the functionality in a method of a superclass, that change is reflected in its subclasses (except in the case of overridden methods – more on these in a moment). However, the converse is not true; changes to a subclass are not reflected in its superclass.

In OO parliance, an inheritance relationship is known as an “Is-A” relationship. To explain this relationship, let’s consider an example where we have a superclass called “Animal” and a subclass called “Cat”. From a code perspective, the “Cat” class inherits the components of the “Animal” superclass. Therefore, as a client looking to use instances of these classes, I see no difference between them. In other words, if the “Animal” superclass defines a method called “eat( )”, I can call that same method on an instance of class “Cat”. Thus, class “Cat” is an “Animal”. This relationship leads to some interesting dynamic programming capabilities that we’ll get into in my next blog.

Defining Inheritance Relationships in ABAP Objects

At this point, you’re probably ready to dispense with all the theory and get into some live code examples. In the code sample below, you’ll see that it is very easy to define an inheritance relationship between two classes.

CLASS lcl_parent DEFINITION.
  PUBLIC SECTION.
    METHODS: a,
             b.

  PRIVATE SECTION.
    DATA: c TYPE i.
ENDCLASS.

CLASS lcl_child DEFINITION
      INHERITING FROM lcl_parent.
  PUBLIC SECTION.
    METHODS: a REDEFINITION,
             d.

  PRIVATE SECTION.
    DATA: e TYPE string.
ENDCLASS.

As you can see in the example above, you can define an inheritance relationship in a class using the INHERITING FROM addition of the CLASS DEFINITION statement. In the example, class “lcl_child” is a subclass of class “lcl_parent”. Therefore, “lcl_child” inherits all of the components defined in class “lcl_parent”. However, not all of these components are directly accessible in class “lcl_child”. Any component defined in the PRIVATE SECTION of “lcl_parent” cannot be accessed in “lcl_child”. However, like any other client of class “lcl_parent”, “lcl_child” can access these private components through defined “getter” methods, etc. Sometimes, you may want to share access to a component of a parent class with its subclasses without opening up access completely. In this case, you can define components in the PROTECTED SECTION. This visibility section allows you to define components that can be accessed in a given class and any of its subclasses only.

Once the inheritance relationship is defined, you can access a subclass’ inherited public components in the same way you would access them in the parent class. Another thing you might notice in the definition of class “lcl_child” is the REDEFINITION addition added to method “a()”. The REDEFINITION addition implies that you want to redefine the way that method “a()” is implemented in the “lcl_child” subclass. Keep in mind that these redefinitions only reshape the code in the IMPLEMENTATION part of the class definition. In other words, you cannot change the interface of the method, etc. – otherwise, you would vioate the “is-a” relationship principal. Inside the redefinition of method “a()” in class “lcl_child”, you can reuse the implementation of the superclass using the “super” pseudoreference variable like this: super->a( ). You can think of the super pseduoreference as a sort of built in reference variable to an instance of the subclass’ superclass.

Some Final Thoughts

Inheritance relationships can be very powerful, allowing you to reuse software components and improve productivity. However, it is important not to get carried away with trying to define complex inheritance hierarchies, etc. Indeed, many top OO researchers advise against the use of inheritance in many design contexts. The bottom line is that there are places where inheritance works, and places it doesn’t.

Another important idea to consider is that inheritance is about more than reuse – it’s about building relationships. One nice thing about these relationships is that you can define inheritance hierarchies where you have a family of classes that are interchangeable. You can then design your programs generically using plug-and-play techniques – something we’ll learn about in my next blog.

To report this post you need to login first.

5 Comments

You must be Logged on to comment or reply to a post.

  1. Thorsten Franz
    James,
    great blog, just like your previous ones. To everybody who enjoys them, I can definitely recommend James’ book “Object-Oriented Programming with ABAP” (http://www.amazon.com/dp/1592292356), which covers the concepts described in the blogs wider and with more detail, but just as lucidly.
    Cheers,
    Thorsten
    (0) 
  2. Christine Newbery
    I very much enjoy you blogs on OO Programming.  I have a question though on why some classes are marked ‘Final’ meaning you can’t inherit from them. 

    SAP provides a BADI for leave processing in the ESS.  They also provide a default implementation class for this BADI called CL_PT_ARQ_REQ_EXIT.  If you don’t implement your own BADI, the code in this SAP class is called.

    This class has many methods, all very useful.  It is also marked ‘Final’.  This means that if you just want to change one of these methods, you have to create your own class from scratch, code the method you want to be different and copy and paste in SAP’s code for the rest of the methods.

    If I understand inheritance correctly, shouldn’t class CL_PT_ARQ_REQ_EXIT not be marked ‘Final’.  This would mean when we create our own implementation of the BADI and our own class, we could make our class inherit from CL_PT_ARQ_REQ_EXIT. 

    That way we would get all of SAP’s code without copying and pasting (and so make sure we get any changes when support stacks are implemented) and would just need to redefine the one method that we would like to be implemented differently.

    Have I misunderstood something?  Why would SAP mark this class as ‘Final’?

    (0) 
    1. James Wood Post author
      Hi Chris,

      As you stated, the final keyword restricts you from inheriting from a given class. I might take that description a step further by suggesting that its purpose is to put a lock on a class (or method) in order to prevent an inheriting class from changing its meaning. For example, imagine that you have a class that defines a method that performs a calculation that can only be implemented in a certain way. Here, it makes sense to mark the method as final in order to prevent novice developers from redefining the behavior of the method incorrectly. Otherwise, you might obtain unexpected results with polymorphic method calls.

      Of course, all of this is highly subjective. It’s like looking at a piece of art: one person might look at it and consider it complete; another might think it still needs more work. Unfortunately, there are no real hard-and-fast rules that determine this, so it’s hard to specualate why SAP decided to finalize this class. However, if I were to guess, I would imagine that this is fairly standard procedure for default BAdI implementations. At least, that’s been my experience with these types of classes.

      Another alternative to inheritance is to use composition. In this case, you define an attribute/local variable of type CL_PT_ARQ_REQ_EXIT and delegate requests to its methods (see the example below). Of course, you have to be careful here to make sure that you are using the class correctly. As I am not familiar with this class, I can’t speak to whether or not composition would make sense in this case. Anyway, hope this helps. Please feel free to follow up if you have any questions. Thanks.

      CLASS ZCL_MY_BADI_IMPL DEFINITION.
        PUBLIC SECTION.
          METHODS:
            constructor,
            some_method.

        PRIVATE SECTION.
          DATA:
            sap_impl TYPE REF TO cl_pt_arq_req_exit.
      ENDCLASS.

      CLASS zcl_my_badi_impl IMPLEMENTATION.
        METHOD constructor.
          CREATE OBJECT sap_impl.
        ENDMETHOD.

        METHOD some_method.
          CALL METHOD sap_impl->…

          “Massage the results/add new functionality…
        ENDMETHOD.
      ENDCLASS.

      (0) 

Leave a Reply