Watch this video to understand the concept of general and more specialized classes.
Inheritance - The "Is A" Relationship
In modeling, we talk about specialization. The implementation of this relationship in a programming language uses the concept of inheritance, in which a new class (the subclass) is derived from an existing one (the superclass). A reliable test to see if there is a genuine inheritance relationship between two classes is to try to say "a subclass is a superclass". If this is clearly true, you have an inheritance relationship. If it is clearly not true, or even sounds a bit strange, you do not have an inheritance relationship and should not implement one as it will likely cause problems further down the line. When testing our model, we can definitely say that "a cargo plane is a plane " and "a passenger plane is a plane".
A class that inherits from a superclass automatically contains all of the components of the superclass. So, for example, the passenger plane class has a manufacturer and a type just as a plane does. This should not be surprising, as a passenger plane is a plane. What may at first appear suprising is that the passenger plane class cannot access its own manufacturer and type. This is because they are private attributes of the superclass and, as such, they are not accessible to the subclass. Later on you will learn a way of allowing a subclass to access components of a superclass without making them fully public.
Defining the Inheritance Relationship
In ABAP, you implement inheritance using the INHERITING FROM addition in the class definition statement. In this example, the passenger plane class is defined as a subclass of the plane class. Note that the subclass knows its superclass, but the airplane class has no idea what subclasses it has (if any).
A subclass may only have one direct superclass.
One Superclass - Any Number of Subclasses
The plane class may have any number of subclasses, but it does not know about any of them.
Each subclass has a single direct superclass. It knows its superclass, but does not know about any sibling classes (other classes that are derived from the same superclass). In our example, the passenger plane class has no knowledge of the cargo plane class.
How to Extend a Subclass
Once you have declared a subclass, you need to add new components to it or change the existing components. This is what turns the mere copy of the plane class into a passenger plane or a cargo plane. Thanks to inheritance, you do not need to implement the class from scratch - you merely extend it by the new components that it needs.
There are three ways to do this:
Declaring New Components
You can extend a subclass by declaring new components. These are visible to the class itself but not to the superclass, and also not to any other classes that inherit from the same superclass. You therefore need to consider whether the new components are only relevant in the current class or if they actually need to be declared in the superclass.
Even though a subclass contains all of the attributes of its superclass, it is not allowed to access the private components directly by itself. Sometimes this is necessary, but there are other times when a superclass needs to let its subclasses access particular attributes or methods without making them fully public. It can do so by declaring them in the protected section. Protected components are visible within the class itself but also to all subclasses.
In the class definition, you introduce the protected section using the statement PROTECTED SECTION. You must always declare the visibility sections in the sequence PUBLIC SECTION - PROTECTED SECTION - PRIVATE SECTION.
You can move an existing component of a class using a quick fix. To do so, place the cursor on the name of the component in ADT and press Ctrl + 1, then choose the quick fix make <element> protected.
Moving a private component to the protected section is a compatible change - you have broadened the visibility of the component. However, making a public component protected is an incompatible change and could cause syntax errors. This is because you have restricted the visibility of the component, which might already have been used outside the inheritance hierarchy.
Superclasses often contain methods that you want to use in a subclass, but their implementations are unsuitable as they do not take into account the particular nature of the subclass. For example, the get_attributes method of the plane class cannot return attributes that are defined in the passenger plane class. However, the passenger plane class still needs a method get_attributes.
In ABAP, you can solve this problem by redefining the instance method get_attributes. When you redefine a method, you write a new implementation for it in the subclass that takes into account things that only the subclass can know. However, the definition of the method stays exactly the same. You must follow these rules:
- The method retains the same name
- You indicate that you want to redefine the method by declaring it in the subclass with the addition REDEFINITION.
- The method has the same visibility as in the superclass
- You must not change the signature of the method
You cannot redefine a static method.
Implementing the Redefinition
When you implement the redefinition of a method, you can call the implementation in the superclass. You do this using the implicit object reference super, which points to the superclass within the current instance. In this way, you can re-use the method implementation from the superclass and then add to it in your own implementation.
You do not need to declare the reference variable super. It is automatically available within the implementation of redefined methods.
Calling the method in the superclass in this way is optional. Sometimes it will be a good idea, sometimes there is nothing to be gained by it.
New Constructor Definition
In a subclass, you may define a new constructor. In contrast to method redefinitions, a constructor may have its own signature. The signature of a constructor will often contain the same parameters as the constructor of the superclass, plus new parameters of its own. This is because the new instance constructor has two tasks - firstly to call the constructor of the superclass, and then to take care of initalizing its own attributes that are specific to the subclass.
As well as defining a new constructor, you can also define a new static constructor in a subclass.
Role of the Constructor
The constructor of a subclass has two functions; it must ensure that the instance of the superclass is properly created, and after that, it can set the initial values of its own attributes.
In our example, since a passenger plane is a plane, there can be no passenger plane instance unless the constructor of the plane class has run successfully to set the manufacturer and type of the new passenger plane. Only after this can the passenger plane class set its own attributes.
The constructor of the subclass must therefore be able to set not only its own attributes, but to pass the required values to the constructor of the superclass. This is why the signature of the constructor in the subclass often contains the entire signature of the constructor that it is required to call.
Sequence of New Constructor Implementation
In the implementation of the new constructor, there is a particular sequence of operations that you must observe. The most important event is the call to the constructor of the superclass. This is obligatory and you call the method using the implicit reference super, just as you can when calling the original implementation of a redefined method. Once again, you do not need to explicitly declare super.
Before you have called the constructor of the superclass, you must not address any instance components of the instance that is under construction. You may address static components of the class and check the correctness of the importing parameters of the constructor. If they are not correct, raise an exception.
Once the constructor of the superclass has run successfully, you may address the instance components of your new instance.
Sequence of Constructor Calls
The figure illustrates the sequence in which static and instance constructors are called. The example assumes that a program wants to instantiate the passenger plane class and that the plane class has not previously been addressed.
When the program tries to create an instance of the passenger plane class, the runtime system automatically calls the static constructors sequentially, starting at the top of the inheritance hierarchy. Once all of the static constructors have run, the runtime system calls the instance constructor of the subclass, which in turn calls the instance constructor of the superclass.