Application Development Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 

Why is this possible in ABAP Objects?

former_member215188
Participant
0 Kudos

So I've being doing ABAP and ABAP Objects for a while now. Then I found out that accessing a protected attribute 'externally' is possible as long as you've initiated the call from inside one of its subclass.

Is anyone else surprised by this? In other languages, I don't think this is allowed. Do you think this is a good feature? Doesn't this make code less secure?

In the code below, you can see that an instance of lcl_child tried to access the protected attribute 'name' of another instance whose type is lcl_parent - a superclass of lcl_child.

REPORT YACCESSTEST.

CLASS lcl_parent DEFINITION.

  PUBLIC SECTION.

    METHODS constructor

      IMPORTING

        p_name TYPE string.

  PROTECTED SECTION.

    DATA name TYPE string.

ENDCLASS.

CLASS lcl_parent IMPLEMENTATION.

  METHOD Constructor.

    name = p_name.

  ENDMETHOD.

ENDCLASS.

CLASS lcl_child DEFINITION INHERITING FROM lcl_parent.

  PUBLIC SECTION.

    METHODS:

      Constructor,

      Test

        IMPORTING p_o_parent TYPE REF TO lcl_parent.

ENDCLASS.

CLASS lcl_child IMPLEMENTATION.

  METHOD Constructor.

    super->Constructor( 'BABY' ).

  ENDMETHOD.

  METHOD Test.

" Should I be able to access this 'PUBLICLY' because

" I'm inside the subclass of lcl_parent? Note that this

" can be a different instance from me.

    WRITE p_o_parent->name.

  ENDMETHOD.

ENDCLASS.

DATA:

  o_parent TYPE REF TO lcl_parent,

  o_child  TYPE REF TO lcl_child.

START-OF-SELECTION.

  CREATE OBJECT o_parent EXPORTING p_name = 'MOMMY'.

  CREATE OBJECT o_child.

* WRITE o_parent->name. " error. not accessible!

  o_child->Test( o_parent ). " outputs 'MOMMY', why possible?!?!?!?!

1 ACCEPTED SOLUTION

matt
Active Contributor
0 Kudos

Here's an example that removes the question of inheritance.

CLASS main DEFINITION.
  PUBLIC SECTION.
    METHODS show IMPORTING i_ref TYPE REF TO main.
    METHODS set IMPORTING i_value TYPE string.

  PRIVATE SECTION.
    DATA: value TYPE string.

ENDCLASS.                    "main DEFINITION

CLASS main IMPLEMENTATION.
  METHOD show.
    WRITE: i_ref->value.
  ENDMETHOD.                    "show

  METHOD set.
    me->value = i_value.
  ENDMETHOD.                    "set

ENDCLASS.                    "main IMPLEMENTATION

START-OF-SELECTION.

  DATA: ref1 TYPE REF TO main,
        ref2 TYPE REF TO main.

  CREATE OBJECT: ref1, ref2.
  ref1->set( 'value of ref1' ).
  ref2->set( 'value of ref2' ).

  ref1->show( ref2 )..

If I pass ref2 to Ref1, then methods within ref1 have access to ref2's private attributes.

I understood private attributes were private to that instance. But it appears they are only private to that class.

15 REPLIES 15

SuhaSaha
Advisor
Advisor
0 Kudos

Hello Emir,

Quite an interesting question

The following things which i come to my mind right now -

  1. The inheritance is defined statically & 'Protected' components are visible to all the (sub)classes in the inheritance tree. When the compiler statically checks if the instance attribute NAME of the class LCL_PARENT is visible in LCL_CHILD, it finds that it can access. I don't see any reason why the compiler should raise any error/warning on that.
  2. There is no need to pass an instance of the parent class to the sub-class. The instance is already available in the runtime via the super variable.

Is anyone else surprised by this? In other languages, I don't think this is allowed.

Tbh i'll surprised if other programming languages do not allow it. How would the compiler determine it statically?


Doesn't this make the code less secure?

No, for me this is very well within the definitions of OOP. You cannot access the protected elements outside the inheritance tree, but inside it.

Let's see what the OO gurus, , , have to say about it.

BR,

Suhas

PS - I have no knowledge of any programming language other than ABAP, so please excuse me for my ignorance.

matt
Active Contributor
0 Kudos

What we have here is the protected attributes of one instance being accessible from another instance.

I wouldn't expect the syntax checker to pick it up (it doesn't pick up when the constructor calls the super-constructor which then calls an overrridden method, even though this ends in a dump), but I would expect it to dump.

I'm surprised.

0 Kudos

Quite surprising for sure. However the "test" method isn't something you would find inside lcl_child class. The method parameter is creating a dependency between two instances which actually might be the same.

Instances from the same class should be independent from each other (at least in 99% of the scenarios I can imagine) so you would have to transfer the "test" method to a different class (for example a writer class). As a consequence it wouldn't be possible to access the attribute without a getter or using the READ-ONLY option for the attribute name.

Katan
Active Participant
0 Kudos

I wrote a little Java program based on your ABAP program, just to verify and the result was the same.

public class TestProtected {

  public static void main(String[] args) {

  Parent p = new Parent("mommy");

  Child c = new Child();

  c.test(p);

  }

}

class Parent {

  protected String name;

  public Parent(String n) {

  name = n;

  }

}

class Child extends Parent{

  public Child(){

   super("baby");

  }

    public void test(Parent p){

   System.out.println(p.name);      //Prints Mommy

   System.out.println(super.name);  // Prints Baby

  }

}

The checks at runtime must only based on the class definitions, not the specific instance. 

Must admit I was suprised about this. I would not write anything in this way, but nevertheless good to know. 

0 Kudos

Hello Katan,

Thanks for the Java program


The checks at runtime must only based on the class definitions, not the specific instance.

Did you mean runtime or design time?


I would not write anything in this way, but nevertheless good to know.

Ditto.

Tbh i was not surprised at the behavior of the compiler/runtime environment, but Matt & you seemed to be so Am i missing something?

BR,

Suhas

0 Kudos

Wrote the same in PHP... and it worked too!!! PHP code- 24 lines - codepad

NOOOoo!!! I don't know what to believe in anymore... Is the world flat? Did Neil Armstrong really land on the moon? lol

0 Kudos

Is the world flat?

The world is not flat, for sure!


Did Neil Armstrong really land on the moon? lol

Now that's debatable

Former Member
0 Kudos

Hi,

There are two instance having same variable "name"

each instance has unique values saved

i.e.

o_parent : name = MOMMY

o_child  : name = BABY

while calling a method Test and pass ref. of o_parent

it will simply represent parent's instance and show a value of MOMMY.

*i'm just beginner in OO if any correct me..

-Avirat

Tomas_Buryanek
Active Contributor
0 Kudos

Ehm. I do not see any problem or strange behavior in your example

You can see output of protected attribute just because you acces it inside class (which is ok).

METHOD Test.

  WRITE p_o_parent->name. "<- here

ENDMETHOD.

Try this. It wont work same like parent acces of protected attribute:

WRITE o_child->name. "name will still not be accesible outside of class


Private attribute is accesible in class only.

Protected attribute is accesible in class and in its subclass.

Public is accesible in class, sublass and outside of class.


-- Tomas --

matt
Active Contributor
0 Kudos

Here's an example that removes the question of inheritance.

CLASS main DEFINITION.
  PUBLIC SECTION.
    METHODS show IMPORTING i_ref TYPE REF TO main.
    METHODS set IMPORTING i_value TYPE string.

  PRIVATE SECTION.
    DATA: value TYPE string.

ENDCLASS.                    "main DEFINITION

CLASS main IMPLEMENTATION.
  METHOD show.
    WRITE: i_ref->value.
  ENDMETHOD.                    "show

  METHOD set.
    me->value = i_value.
  ENDMETHOD.                    "set

ENDCLASS.                    "main IMPLEMENTATION

START-OF-SELECTION.

  DATA: ref1 TYPE REF TO main,
        ref2 TYPE REF TO main.

  CREATE OBJECT: ref1, ref2.
  ref1->set( 'value of ref1' ).
  ref2->set( 'value of ref2' ).

  ref1->show( ref2 )..

If I pass ref2 to Ref1, then methods within ref1 have access to ref2's private attributes.

I understood private attributes were private to that instance. But it appears they are only private to that class.

Tomas_Buryanek
Active Contributor
0 Kudos

"value" is private for class not for each object (ref1, ref2..). So ref1 value is visible from ref2 instance.

Info from SAP Help on "PRIVATE SECTION" keyword:

  • The class is the smallest encapsulation unit in ABAP Objects. This means that a method can use all private components of all instances of the same class...

Hope this helps understanding

-- Tomas --

matt
Active Contributor
0 Kudos

Well - it's nice to learn something new. It seems common across OO languages, but still seems a bit weird.

FabioPagoti
Active Contributor
0 Kudos

Nice example Matthew!

A misunderstanding could be solved making "show" a static method.

0 Kudos

Glad to know I'm not the only one

I've always thought of instance->attribute as a public way of accessing regardless of where the call has been made since you are essentially accessing from the 'outside' of the instance.. I giess i have to remove that from my brain somehow heheh Thanks Matthew!

0 Kudos

Yes. This is specially true.

This is quite troubling because it makes it way too easy to access protected variables through 'psuedo' inheritance.

I like it that ABAP requires the subclass to call it's superclass' constructor. This gives you a sense of 'responsibility' in creating subclasses specially if you are simply just accessing a wanted attribute. However, because of this, you dont even have to instantiate anything - Just create a static method. So you can do whatever in the constructor.

Ex. below.. I want to get cl_gui_alv_grid from an salv object. r_controller is a protected variable and cl_salv_model_list is the superclass of cl_salv_table.

CLASS lcl_hack_salv DEFINITION INHERITING FROM cl_salv_model_list.

   PUBLIC SECTION.

     CLASS-METHODS:

       GetGrid

         IMPORTING

           p_o_model TYPE REF TO cl_salv_model

         RETURNING

           VALUE(r_o_grid) TYPE REF TO cl_gui_alv_grid.

ENDCLASS.

CLASS lcl_hack_salv IMPLEMENTATION.

   METHOD GetGrid.

     CHECK p_o_model->r_controller->r_adapter IS BOUND.

     CALL METHOD p_o_model->r_controller->r_adapter->('GET_GRID')

       RECEIVING value = r_o_grid.

   ENDMETHOD.

ENDCLASS.

*** call

DATA: o_alv   TYPE REF TO cl_salv_table,

           o_grid TYPE REF TO cl_gui_alv_grid,


  l_o_grid ?= lcl_hack_salv=>getgrid( r_o_alv ). " Static Call! No instantiation required!!!!!