Wednesday, 25 November 2020

Classes in ABAP

Classes are fundamental structures that we need to understand and master to model entities.

A class can represent anything; a document, a vehicle, animal, or anything that has traits and behaviours.

Classes in ABAP are coded in two steps: first of all, you code the definition part and then the implementation part.

The definition part is the place where you define all the data and methods that are going to be used in the class.

Here you must specify the public, private, and protected sections also they have to be placed in the order you see in the code otherwise you will a syntax error.

SAP ABAP Tutorial and Material, SAP ABAP Exam Prep, SAP ABAP Certification, SAP ABAP Development

The following code shows the structure of a class:

CLASS <Name of the class> DEFINITION.

PUBLIC SECTION.

PROTECTED SECTION.

PRIVATE SECTION.

ENDCLASS.

CLASS <Name of the class> IMPLEMENTATION.

ENDCLASS.

For a better illustration let’s create complete example to show more details of a class.

Please create a new program and name it ZCLASS and paste the following code.

report  zclass.

class cl_animal definition abstract.

  public section.

    methods: constructor importing i_name type string, " Visible to everyone

             make_a_sound,

             my_name_is,

             get_type,

             introduce_me.

  protected section. " Visible only in child classes

    data p_class type string.

  private section. " Visible only internally

    data p_name type string.

endclass.

class cl_animal implementation.

  method constructor.

    p_name = i_name.     " p_name was defined already in the definition part of the class as private

    p_class = 'Unknown'. " p_class was defined already in the definition part of the class as protected

  endmethod.

  method make_a_sound.

    write 'Nothing'.

  endmethod.

  method my_name_is.

    write: / 'My name is: ', p_name.

  endmethod.

  method get_type.

    write: / 'I''m type of: ', p_class.

  endmethod.

  method introduce_me.

    me->my_name_is( ). " The keyword 'me' is used to specify class member. Is the equivalent of the keyword 'this' in C#

    make_a_sound( ).

    get_type( ).

  endmethod.

endclass.

class cl_dog definition inheriting from cl_animal.

  public section.

    methods: constructor importing i_dog_name type string,

             make_a_sound redefinition. " Change the behaviour of the method. Reimplement the code.

endclass.

class cl_dog implementation.

  method constructor.

    super->constructor( i_dog_name ). " Initialize the constructor and internally pass the parameter to the abstract class

    p_class = '"Dog"'.                " This is the protected member which is visible only in child classes

  endmethod.

  method make_a_sound.

    write: / 'My sound is:', 'Woof, woof'.

  endmethod.

endclass.

class cl_cat definition inheriting from cl_animal.

  public section.

    methods: constructor importing i_cat_name type string,

             make_a_sound redefinition.

endclass.

class cl_cat implementation.

  method constructor.

    super->constructor( i_cat_name ).

    p_class = '"Cat"'.

  endmethod.

  method make_a_sound.

    write: / 'My sound is:', 'Meow, meow'.

  endmethod.

endclass.

class cl_animal_factory definition.

  public section.

    class-methods create_animal importing i_animal type i returning value(r_animal) type ref to cl_animal. " Class method, in C# this is called a static method

endclass.

class cl_animal_factory implementation. " Factory pattern

  method create_animal.

    case i_animal.

      when 1.

        data dog type ref to cl_dog.

        create object dog exporting i_dog_name = 'Sparky'.

        r_animal = dog. " It is returned a cl_dog instance.

      when 2.

        data cat type ref to cl_cat.

        create object cat exporting i_cat_name = 'Fluffy'.

        r_animal = cat. " It is returned a cl_cat instance.

      when others.

    endcase.

  endmethod.

endclass.

class cl_introducer definition.

  public section.

    class-methods introduce importing i_animal type ref to cl_animal. " Here the method receives a cl_animal type parameter

endclass.

class cl_introducer implementation.

  method introduce.

    if i_animal is not initial.

      i_animal->introduce_me( ).

    else.

      write / 'I''m nothing'.

    endif.

  endmethod.

endclass.

start-of-selection.

  data wa_animal type ref to cl_animal.

  wa_animal = cl_animal_factory=>create_animal( 1 ).

  cl_introducer=>introduce( wa_animal ). " The i_animal parameter is implicitly specified. Useful when is only one parameter.

  write /.

  wa_animal = cl_animal_factory=>create_animal( 2 ).

  cl_introducer=>introduce( i_animal = wa_animal ). "  The i_animal parameter is explicitly specified and is necessary its use when is more than one paramter.

  write /.

  wa_animal = cl_animal_factory=>create_animal( 3 ).

  cl_introducer=>introduce( wa_animal ).

By definition, classes can be created as normal, abstract, and inherited. For example:

For any given class is only necessary the following:

class myclass definition.

endclass.

For an abstract class the code is:

class myclass definition abstract.

endclass.

This kind of class cannot be instantiated.

And for an inherited class or subclass the code is:

class myclass definition inheriting from abstractclass.

endclass.

The public section is the place where you declare information that is visible outside the class.

The private section has members that are internal and can’t be exposed outside the class even within subclasses.

The protected section has information that is exposed or is visible only internally and along with all the child classes.

In every section, you can specify instance data and methods and also class data and methods.

The difference between instance members and class members is that for the first ones it is necessary to create the object (we’ll get there soon) to use those members and in the second ones is not necessary the instantiation, we can use them directly from the class with a special sign (=>) and for the other instance data and methods it is used the (->) sign.

class cl_animal definition abstract.

  public section.

    methods: constructor importing i_name type string, " Visible to everyone

             make_a_sound,

             my_name_is,

             get_type.

  protected section. " Visible only here and in child classes

    data p_class type string.

  private section. " Visible only internally

    data p_name type string.

endclass.

The implementation part is used to code the methods. Here you code the behavior of the class and you can see that none of the members including the parameters are presented and that’s because they were already defined previously in the definition part of the class.

class cl_animal implementation.

  method constructor.

    p_name = i_name.     " p_name was defined already in the definition part of the class as private

    p_class = 'Unknown'. " p_class was defined already in the definition part of the class as protected

  endmethod.

  method make_a_sound.

    write 'Nothing'.

  endmethod.

  method my_name_is.

    write: / 'My name is: ', p_name.

  endmethod.

  method get_type.

    write: / 'I''m type of: ', p_class.

  endmethod.

endclass.

The next part of the code consists of how you can inherit classes.

This is a powerful concept because you get the functionality that already exists and depending on the definition, it is possible to change the behavior of a method.

class cl_dog definition inheriting from cl_animal.

  public section.

    methods: constructor importing i_dog_name type string,

             make_a_sound redefinition. " Change the behaviour of the method. Reimplement the code.

endclass.

class cl_dog implementation.

  method constructor.

    super->constructor( i_dog_name ). " Initialize the constructor and internally pass the parameter to the abstract class

    p_class = '"Dog"'.                " This is the protected member which is visible only in child classes

  endmethod.

  method make_a_sound.

    write: / 'My sound is:', 'Woof, woof'.

  endmethod.

endclass.

The method ‘make_a_sound’ was overrwritten, or better said, overridden to act differently from the original class. The same applies to the ‘cl_cat’ class.

One powerful trait about classes is that we can make more with less and we can also create a common interface to make classes of the same type could act differently.

This concept is called ‘polymorphism’ and a good example of this is the following implementation using the Factory pattern:

class cl_animal_factory definition.

  public section.

    class-methods create_animal importing i_animal type i returning value(r_animal) type ref to cl_animal. " Class method, in C# this is called a static method

endclass.

class cl_animal_factory implementation. " Factory pattern

  method create_animal.

    case i_animal.

      when 1.

        data dog type ref to cl_dog.

        create object dog exporting i_dog_name = 'Sparky'.

        r_animal = dog. " It is returned a cl_dog instance.

      when 2.

        data cat type ref to cl_cat.

        create object cat exporting i_cat_name = 'Fluffy'.

        r_animal = cat. " It is returned a cl_cat instance.

      when others.

    endcase.

  endmethod.

endclass.

class cl_introducer definition.

  public section.

    class-methods introduce importing i_animal type ref to cl_animal. " Here the method receives a cl_animal type parameter

endclass.

class cl_introducer implementation.

  method introduce.

    if i_animal is not initial.

      i_animal->introduce_me( ).

    else.

      write / 'I''m nothing'.

    endif.

  endmethod.

endclass.

Here we define a class which creates different types of instances of cl_animal class and the advantage on this is that we can use the cl_introduce class to act on any child class of cl_animal type.

The purpose is to not change the interface and use a common procedure that is going to be prepared to function on these classes.

Finally the code ends like this:

start-of-selection.

  data wa_animal type ref to cl_animal.

  wa_animal = cl_animal_factory=>create_animal( 1 ).

  cl_introducer=>introduce( wa_animal ). " The i_animal parameter is implicitly specified. Useful when is only one parameter.

  write /.

  wa_animal = cl_animal_factory=>create_animal( 2 ).

  cl_introducer=>introduce( i_animal = wa_animal ). "  The i_animal parameter is explicitly specified and is necessary its use when is more than one paramter.

  write /.

  wa_animal = cl_animal_factory=>create_animal( 3 ).

  cl_introducer=>introduce( wa_animal ).

Notice that for the ‘introduce’ class-method of class ‘cl_introducer’ you can specify implicit or explicitly the parameter. When methods have more than one parameter is necessary to explicitly specify the parameters.

The output of the program is the following:

My name is:  Sparky

My sound is: Woof, woof

I'm type of:  "Dog"

My name is:  Fluffy

My sound is: Meow, meow

I'm type of:  "Cat"

I'm nothing

This was a simple example where it is shown how to code classes in ABAP.

No comments:

Post a Comment