Few days back, I came across this challenging question on SCN about Inheritance within ABAP Objects specifically to the Protected Section.
Fellow member Ethan Zhang on SCN recently posted a question – Confused with abap inheritance? Lets try to understand the question with different example:
I have a super class LCL_CAR and I have inherited subclass LCL_SPORTS_CAR and LCL_SEDAN. Check out the UML to see the Class hierarchy and class components.
Pay a close attention to attribute PARENT. This attribute is with reference to LCL_CAR. I have made it as public, as I wanted to set a different object altogether as PARENT.
Lets check out this code..
REPORT ztest_np_PROTECTED. *&---------------------------------------------------------------------* *& Purpose - PROTECTED section access using Reference variable for *& Super class *& Author - Naimesh Patel *& URL - http://zevolving.com/?p=1898 *&---------------------------------------------------------------------* * CLASS lcl_car DEFINITION. PUBLIC SECTION. METHODS: start. PROTECTED SECTION. METHODS: start_engine. ENDCLASS. "lcl_car DEFINITION * CLASS lcl_sports_car DEFINITION INHERITING FROM lcl_car. PUBLIC SECTION. DATA parent TYPE REF TO lcl_car. PROTECTED SECTION. METHODS: start_engine REDEFINITION. ENDCLASS. "lcl_sports_Car DEFINITION * CLASS lcl_sedan DEFINITION INHERITING FROM lcl_car. PUBLIC SECTION. DATA parent TYPE REF TO lcl_car. PROTECTED SECTION. METHODS: start_engine REDEFINITION. ENDCLASS. "lcl_sedan DEFINITION START-OF-SELECTION. DATA: lo_ferari TYPE REF TO lcl_sports_car. DATA: lo_any_car TYPE REF TO lcl_car. * CREATE OBJECT lo_any_car. CREATE OBJECT: lo_ferari. * lo_ferari->parent = lo_any_car. lo_ferari->start( ). * * * CLASS lcl_car IMPLEMENTATION. METHOD start. WRITE: / 'Starting Car'. me->start_engine( ). ENDMETHOD. "start METHOD start_engine. WRITE: / 'Starting car engine'. ENDMETHOD. "start_Engine ENDCLASS. "lcl_car IMPLEMENTATION * CLASS lcl_sports_car IMPLEMENTATION. METHOD start_engine. WRITE: / 'Starting Sports Car engine'. parent->start_engine( ). ENDMETHOD. "start_Engine ENDCLASS. "lcl_sports_Car IMPLEMENTATION * CLASS lcl_sedan IMPLEMENTATION. METHOD start_engine. WRITE: / 'Starting Sedan engine'. parent->start_engine( ). ENDMETHOD. "start_Engine ENDCLASS. "lcl_sedan IMPLEMENTATION
Output of the above code lines:
Here I’m instantiating the object for a Sports car LO_FERARI and a Generic car LO_ANY_CAR. I set the LO_ANY_CAR as the PARENT object for the Sports car object LO_FERARI. Within the method START_ENGINE, I can call the method START_ENGINE for the LO_ANY_CAR as well, which is PROTECTED. Ahhh, how did this happen?
So far I was under impression which is true in many languages that PROTECTED components can be only accessed within the Object reference of the Subclass using the ME or SUPER addition. But here, as you can see, we can call the method START_ENGINE of the PARENT without any Syntax errors or warnings.
SAP Help on Protected Section, mentions this:
In subclasses, it is not possible to access the protected components of the superior classes using reference variables of the type of the superior class, because otherwise an attribute of an object of the dynamic type of the superior class or another subclass could be changed. In the latter case, a warning is triggered by the extended syntax check.
It clearly mentions that I can’t reference Protected components using the reference variable, but it turns out, I can access them. I can also see that the Warning message comes up in Syntax Check Warnings section while performing the Extended Program Check in SLIN.
My take on not to use the reference variable of Super class
Since the PROTECTED attributes are visible to the Inherited objects, system would allow them to have access of PROTECTED components in the Subclass.
Even though, it is allowed, you should take extra caution when using this approach to gain access of the PROTECTED attributes in the Subclass having a different Object reference than itself. As long as you are using the PROTECTED attributes referring to its own object reference ME->, it would be ok and robust.
If you use any other object reference and gain access of PROTECTED attributes, you may run into issues, when the object assigned this object reference is more specific or having reference generated using different branch of inheritance. This could definitely happen, if your application gets extended in future. Your Application may be as robust as it could be when accessing these attributes using other object reference.
Check this code lines. Here I have another object for LCL_SEDAN as LO_BMW. I can set the PARENT of the sports car LO_FERARI as Sedan LO_BMW, which completely doesn’t make sense.
Revised code for setting up different parent
DATA: lo_ferari TYPE REF TO lcl_sports_car. DATA: lo_bmw TYPE REF TO lcl_sedan. DATA: lo_any_car TYPE REF TO lcl_car. CREATE OBJECT lo_any_car. CREATE OBJECT: lo_ferari, lo_bmw. lo_ferari->parent = lo_any_car. lo_ferari->start( ). * SKIP 2. WRITE: / 'Any car as Parent'. lo_bmw->parent = lo_any_car. lo_bmw->start( ). * SKIP 2. WRITE: / 'Ferrari as Parent for BMW'. lo_bmw->parent = lo_ferari. lo_bmw->start( ).
If you see the output, it would also execute the code for the START_ENGINE of the LO_BMW.
Extended Syntax check in ABAP Editor produces a warning, which can’t be hidden using any Pragmas or Pseudo comment. That says like – I don’t want you to use this. But if you want to use it use anyways, I wont allow you to hide that from others.
What do you think? Please drop me a comment and let me know.