Copyright 2021 - BV TallVision IT

You are a variabele and you have been defined on a method of a class that has a super class and is itself a subclass. This article explains visibility in a very practical way. From locally defined variables to Public/Protected/Private variables on local classes and the same on global classes.

A bottom-up approach to the topic of visibility: starting with a locally defined variabele: 

METHOD cheesebomber.
  data: lv_my_very_own type sflight. 

ENDMETHOD. 

The visibility of the lv_my_very_own variable is only from within the method. It is also the poorest possible visibility an attribute (variable) can get.

The flighing machine (local) class

The flighing machine class is a simple class which holds a set of attributes and a few methods to access the attributes. Note that the attributes are protected in 2 possible ways: the NAME is a read-only attribute and the other attributes are all private.

CLASS lcl_flighing_machine DEFINITION.

  PUBLIC SECTION.
    DATA: gv_name type string read-only.

    METHODS: constructor importing name type string,
             get_information
               exporting engine type string
                         capacity type string,
             set_information
               importing engine type string optional
                         capacity type string optional.

  PRIVATE SECTION.
     DATA: gv_engine type string,
           gv_capacity type string.

ENDCLASS.

The implemantation of the flighing machine class (including all coding)

CLASS lcl_flighing_machine IMPLEMENTATION.

  METHOD constructor.
    gv_name = name.
  ENDMETHOD.
  METHOD get_information.
    engine = gv_engine.
    capacity = gv_capacity.
  ENDMETHOD.
  METHOD set_information.
    if engine is supplied.
      gv_engine = engine.
    endif.
    if capacity is supplied.
      gv_capacity = capacity.
    endif.
  ENDMETHOD.

ENDCLASS.

The below example shows how the class can be used: instantiate for a flighing machine named "Plane" and set the information. Note that the name can not be changed from outside the class (as it is a readonly field).

DATA: go_flying_machine TYPE REF TO lcl_flighing_machine.

START-OF-SELECTION.
  CREATE OBJECT go_flying_machine EXPORTING name = 'Plane'.

  go_flying_machine->set_information( 
    engine = 'Propellor' capacity = '12 persons' ).

  write: go_flying_machine->gv_name,
    go_flying_machine->gv_engine, 
    go_flying_machine->gv_capacity.

Note that the red lines above can not be compiled: attributes GV_ENGINE and GV_CAPACITY are defined as Private attributes. Error "Access to private attribute "GV_ENGINE" is not allowed" will appear. Method get_information will need to be used to fetch (a copy of) the attributes to work with. So effectively: even attributes that are not visible, can reveal it's values/content, by requesting a method to pass these values. Is such method is made available of course.

go_flying_machine->gv_name = 'Hovercraft'. 

Will produce the error: Write access to the READ-ONLY attribute "GV_NAME" is not allowed outside the class/interface

Some considetations on the example we've seen now:

  • The GV_ENGINE attribute is defined as Private - thus "are only visible in the methods of the same class". Method GET_INFORMATION is such method.
  • The developer of this class has a strong tool in his hands: his/her data can be made available through setter/getter methods, which means that checks can be done on the data that is passed on. Data on the class can be checked, and data integrity can be insured.
  • So what if the class holds attributes that are not allways filled in ? Setter/getter methods (or just getter methods) can check this and populate the data on demand. Or the simple fact that certain data is not always available (and thus not reliable for outsiders to use) the data should not be available at all (a Private attribute).

The plane (sub)class

A new class will be introduced, which describes a more specific subject: the plane. We will see that the Private attributes are not available to the subclass. The definition:

CLASS lcl_plane DEFINITION
  INHERITING FROM lcl_flighing_machine.

  PUBLIC SECTION.
    DATA: gv_id type string,
          gv_weight type string.

    METHODS: constructor importing
               name type string
               id type string,
             visibility_tester.

ENDCLASS.

The attributes (and methods) from the lcl_flighing_machine class are available from the lcl_plane class. And in addition there are 2 new attributes available, gv_id and gv_weight which are both in the Publicsection. The implementation:

CLASS lcl_plane IMPLEMENTATION.
  METHOD constructor.
    super->constructor( name = name ).
    gv_id = id.
  ENDMETHOD.
  METHOD visibility_tester. 
* Example coding to go here    
  ENDMETHOD. 
ENDCLASS.

The constructor of lcl_plane will also call the constructor of the class it inherits from. So now our coding example can be altered somewhat, to move from class use to sub class use:

DATA: go_plane TYPE REF TO lcl_plane.

START-OF-SELECTION.
  CREATE OBJECT go_plane
    EXPORTING name = 'Plane'
              id = 'AA7865'.

  go_plane->set_information( 
    engine = 'Propellar' capacity = '12 persons' ).

  write: go_plane->gv_name.

In effect: we have the same example as before, only this time it is composed from the sub class lcl_plane involving the super class lcl_flighing_machine.

With the setup shown above, try to go through these additions (no really: if you try this out, a lot will fall into place).

  METHOD visibility_tester.
* Example coding to go here
    gv_engine = 'Jet'. 
  ENDMETHOD.

Error message: Field "GV_ENGINE" is unknown. It is neither in one of the specified tables nor defined by a "DATA" statement.

This error can be solved, by changing the PRIVATE SECTION to PROTECTED SECTION on the super class (lcl_flighing_machine). Try this !

And here's another one: Protected means that methods from a sub class can access the attributes (or methods). But what if access from outside the class is required ?

  WRITE: go_plane->gv_name.
  WRITE: go_plane->gv_engine.

Solve this error by moving the attributes to the Public section (note that renaming PROTECTED to PUBLIC won't help, as there is already a Public section.

This demonstrates visibility in a local class, showing how data is accessed and what happens if it is not available.

Global classes

This whole setup works in exactly the same way in global classes (thus not defined in your Abap source code, but in SE24). The only difference being: globally defined classes can be called from local reports, thus visibility matters are taken further than just your report. Visibility settings on global classes are usually set up right, where in local classes everything tends to live in the Public section. That's a bad habit really...