Wśród  możliwości oferowanych przez język ABAP znaleźć można między innymi „wsparcie reguł programowania obiektowego”. Jest to funkcjonalność często niedoceniana, zwłaszcza przez początkujących programistów, jednakże ze względu na jej możliwości, a także na to, że obiektowość pojawia się także w wielu innych językach programowania, nie powinno się jej ignorować.

 

Nadrzędnym celem przy tworzeniu paradygmatu programowania obiektowego było umożliwienie tworzenia w kodzie reprezentacji obiektów istniejących w świecie rzeczywistym. Obiekty w prawdziwym świecie mogą być opisane przy użyciu stanów (wszelkie dane opisujące obiekt) oraz zachowań (czyli tego, co obiekt może zrobić, bądź co można zrobić na obiekcie; zachowania mogą zmieniać stan obiektu, mogą także służyć do komunikacji z innymi obiektami). Przykładowo, obiekt „konto bankowe” może być opisany przy pomocy danych takich jak numer konta, dane osobowe posiadacza, data założenia konta, ilość pieniędzy znajdująca się na koncie w danym momencie itp. Do obiektu „konto bankowe” można też przypisać zachowania takie jak wpłata i wypłata środków, dokonanie przelewu, zmiana danych właściciela, zamrożenie konta itd.

 

Programowanie obiektowe ma na celu odtworzenie w kodzie rzeczywiście istniejących obiektów w pisanych programach. Stany obiektów są w kodzie opisywane w atrybutach, zachowania z kolei są przedstawiane poprzez metody (metody i atrybuty są zbiorczo określane jako komponenty). Swego rodzaju szablonami dla obiektów są klasy – to właśnie w definicjach klas przechowywane są informacje o tym, jakie komponenty będą służyły do opisania danych obiektów. Instancjami klas są pojedyncze obiekty - przykładowo, instancją klasy „konto bankowe” może być „konto numer XXXX”.

 

Paradygmat programowania obiektowego opiera się na czterech głównych założeniach. Są to:

 

1. Abstrakcja

Abstrakcja polega na zmapowaniu obiektów z prawdziwego świata w taki sposób żeby brane pod uwagę były z jednej strony te atrybuty obiektu, które są niezbędne do prawidłowego działania programu, a z drugiej te, które mogą być wspólne dla większej ilości obiektów.

 

2. Dziedziczenie

Klasy obiektów mogą posiadać swoje podklasy. Obiekty w podklasach są opisywane przy pomocy komponentów „dziedziczonych” z nadklasy. Co więcej, podklasy mogą także posiadać swoje własne, niewystępujące w nadklasie metody i atrybuty, jak również nadpisywać metody z nadklasy. Najczęściej podklasy są tworzone, aby móc tworzyć bardziej wyspecjalizowane obiekty względem tych należących do nadklasy. Przykładowo, podklasami klasy „konto bankowe” mogłyby być „konto oszczędnościowe”, „konto walutowe”, „konto firmowe” itd.

 

 

3. Polimorfizm

Polimorfizm zakłada, że jedna metoda należąca do kilku różnych klas może w każdej z nich działać w zupełnie inny sposób. Polimorfizm można uzyskać między innymi poprzez redefiniowanie metod w podklasach.

 

4. Enkapsulacja

Możliwe jest utworzenie komponentów prywatnych, czyli takich, które są „ukryte przed światem zewnętrznym” i dostępne tylko i wyłącznie wewnątrz danej klasy. Enkapsulacja zakłada, że dostęp do prywatnych komponentów może być zapewniony tylko poprzez wywoływanie odpowiednich metod publicznych danej klasy, czyli takich, do których dostęp z zewnątrz jest dozwolony. Pomaga to ograniczyć możliwość niepożądanej manipulacji obiektami.  W języku ABAP wyróżnia się komponenty publiczne („public”, dostępne wszędzie), chronione („protected”, dostępne tylko w obrębie danej klasy oraz dziedziczących z niej podklas), oraz prywatne („private”, dostępne tylko w obrębie danej klasy).

 

PRAKTYKA

TWORZENIE KLAS

W języku ABAP klasy można tworzyć na dwa sposoby – możliwe jest utworzenie klas lokalnych, które istnieć będą tylko w obrębie jednego programu, bądź też klas globalnych, do których można odwoływać się w całym systemie.

 

1. Klasy lokalne

Deklaracja klasy lokalnej składa się z dwóch części – definicji i implementacji. Definicja klasy musi zawierać wszystkie komponenty danej klasy. Przykład kodu definiującego klasę:

CLASS nazwa_klasy DEFINITION.

DATA: [deklaracje atrybutów].

METHODS: metoda1, metoda2.

ENDCLASS.

Dodatkowo, wszystkie definiowane komponenty powinny być przypisane do odpowiedniej sekcji – publicznej, chronionej bądź prywatnej. Oznacza to, że poprawna definicja klasy powinna wyglądać następująco:

CLASS nazwa_klasy DEFINITION.

PUBLIC SECTION.

[definicje publicznych komponentów].

PROTECTED SECTION.

[definicje chronionych komponentów].

PRIVATE SECTION.

[definicje prywatnych komponentów].

ENDCLASS.

 

Co więcej, w przypadku atrybutów możliwe jest dodanie opcji umożliwiającej to, że dany atrybut może być zmieniony tylko wewnątrz danej klasy, choć jego wartość może być odczytana także poza klasą. W tym celu należy przy definiowaniu atrybutu wykorzystać słowo kluczowe READ-ONLY.

DATA: atrybut TYPE typ READ-ONLY.

 

Należy pamiętać, że metody mogą, podobnie jak funkcje czy moduły funkcyjne, zawierać parametry wejścia i wyjścia oraz wyjątki, opisane słowami kluczowymi IMPORTING, EXPORTING, CHANGING, RAISING, EXCEPTIONS. Ponadto, jeżeli metoda ma zwracać pojedynczą wartość, możliwe jest użycie słowa kluczowego RETURNING. Metody wykorzystujące słowo kluczowe RETURNING nazywane są metodami funkcjonalnymi.

CLASS klasa DEFINITION.

PUBLIC SECTION.

METHODS: metoda1 IMPORTING parametr1 EXPORTING parametr2.

ENDCLASS.

 

Komponenty mogą być statyczne bądź instancyjne. Komponent instancyjny to taki, który istnieje osobno dla każdej instancji klasy. Komponent instancyjny istnieje w tylu niezależnych od siebie nawzajem kopiach, ile instancji danej klasy w danym momencie istnieje. Komponent statyczny z kolei istnieje tylko w jednej kopii, wspólnej dla wszystkich instancji klasy. Domyślnie wszystkie komponenty są instancyjne, aby zdefiniować komponent statyczny należy użyć słowa kluczowego „CLASS-”. Przykładowo, w poniższym kodzie metoda M1 i atrybut A1 to komponenty instancyjne, a metoda M2 i atrybut A2 to komponenty statyczne.

DATA: A1.

CLASS-DATA: A2. 

METHODS: M1.

CLASS-METHODS: M2.

 

Implementacja klasy musi zawierać logikę wszystkich metod wymienionych w definicji. Przykładowa implementacja:

CLASS  nazwa_klasy IMPLEMENTATION.

METHOD metoda1.

[kod metody].

ENDMETHOD.

METHOD metoda2.

[kod metody].

ENDMETHOD.

ENDCLASS.

 

Specyficznymi metodami, które wywoływane są podczas tworzenia instancji klasy są tak zwane konstruktory. W języku ABAP istnieją dwa rodzaje konstruktorów – instancyjne oraz statyczne. Konstruktor instancyjny to metoda (zawsze nazywająca się CONSTRUCTOR), która wywoływana jest automatycznie podczas tworzenia obiektu danej klasy i wywoływana jest dokładnie jeden raz dla każdej nowo tworzonej instancji. Konstruktor musi być zdefiniowany w publicznej sekcji klasy i nie może posiadać parametrów innych niż wejściowe, może jednak posiadać wyjątki. Konstruktor statyczny to metoda (zawsze nazywająca się CLASS_CONSTRUCTOR) wywoływana tylko raz w trakcie działania programu, przed pierwszą akcją wywołującą daną klasę (wywołanie statycznej metody, odczytanie wartości atrybutu, utworzenie instancji). Konstruktor statyczny musi być zdefiniowany w publicznej sekcji klasy, nie może posiadać parametrów wejściowych ani wyjątków.

 

2. Klasy globalne.

Klasy globalne można tworzyć przy pomocy narzędzi Class Builder (transakcja SE24) bądź Object Navigator (transakcja SE80). Przy tworzeniu klasy globalnej możliwe jest określenie instancyjności, czyli tego, jak mogą być tworzone instancje klasy (1). Dostępne opcje instancyjności to „Zabezpieczony” (instancje danej klasy mogą być tworzone tylko wewnątrz niej bądź wewnątrz dziedziczących z niej podklas), „Publiczna” (instancje danej klasy mogą być tworzone wszędzie), „Abstrakcyjny” (instancje danej klasy nie mogą być nigdzie tworzone) oraz „Prywatny” (instancje danej klasy mogą być tworzone tylko wewnątrz niej). Ponadto, możliwe jest także określenie, czy zezwala się by dana klasa mogła mieć podklasy – aby tak było, należy odznaczyć checkbox „Końcowy” (2).

 

 

 

Istnieje możliwość utworzenia takiej klasy, dla której w danym momencie może istnieć tylko jedna jej instancja. Klasa taka jest określana jako „singleton”. Singleton musi posiadać instancyjność na poziomie prywatnym, być klasą końcową, a jego instancje mogą być tworzone tylko przy pomocy statycznego konstruktora.

Klasę globalną można utworzyć na dwa równoważne sposoby. Pierwszy z nich to sposób oparty na tekście źródłowym, w którym klasę deklaruje się pisząc kod w sposób identyczny jak w przypadku klas lokalnych. SAP oferuje jednakże ułatwienie w postaci edytora klas opartego na formularzu, dzięki któremu zarządzanie tworzonymi elementami klasy jest bardziej przejrzyste.

 

 

 

RELACJE MIĘDZY KLASAMI

ABAP obsługuje dwa rodzaje relacji między klasami. Pierwszą jest wspomniane już dziedziczenie, drugą – zaprzyjaźnienie (ang. „friendship”).

Jak już zostało wspomniane, dziedziczenie polega na tym, że jedna klasa (podklasa) dziedziczy wszystkie komponenty po innej klasie (nadklasie). Ponadto, podklasa może posiadać swoje własne komponenty (takie, które w nadklasie nie występują), bądź też redefiniować definicje metod dziedziczonych z nadklasy. Poniższy kod pokazuje definicję klasy podklasa dziedziczącej po klasie nadklasa, w której dodatkowo zredefiniowana zostaje odziedziczona z nadklasy metoda "metoda1". Dla tak zadeklarowanej podklasy nie trzeba powtarzać definicji komponentów, które już zostały zdefiniowane w nadklasie.

CLASS podklasa DEFINITION INHERITING FROM nadklasa.

PUBLIC SECTION.

METHODS: metoda1 REDEFINITION.

ENDCLASS.

Zaprzyjaźnienie to inny rodzaj relacji. Jeżeli klasa A jest zaprzyjaźniona z klasą B, to klasa B (jak również jej podklasy) uzyskuje dostęp do chronionych oraz prywatnych komponentów klasy A (nie uzyskuje jednak dostępu do komponentów podklas klasy A). Opisany przykład zaprzyjaźnienia klas A i B można zapisać w kodzie w następujący sposób:

CLASS klasa_a DEFINITION FRIENDS klasa_b.

[…]

ENDCLASS.

Należy pamiętać, że zaprzyjaźnienie to relacja jednostronna – klasa A nie będzie mogła korzystać z prywatnych i chronionych komponentów klasy B, o ile klasa B nie zostanie zaprzyjaźniona z klasą A.

 

UŻYWANIE KLAS

Tworzenie obiektów (czyli instancji klas) ma miejsce przy użyciu słowa kluczowego CREATE OBJECT. Przykład:

DATA: instancja TYPE REF TO klasa.

CREATE OBJECT instancja.

Jeżeli konstruktor instancyjny danej klasy posiada zmienną wejściową bądź ma zadeklarowane wyjątki, możemy się do nich odnieść podczas tworzenia klasy w następujący sposób:

CREATE OBJECT instancja EXPORTING zmienna EXCEPTIONS wyjątek. 

Następujący kod pozwala wywołać metody instancyjne klasy:

CALL METHOD instancja->metoda.

Metody statyczne klasy można z kolei wywołać w następujący sposób:

CALL METHOD klasa=>metoda.

W analogicznych sposób można uzyskać dostęp do atrybutów klas:

instancja->atrybut_instancyjny.
klasa=>atrybut_statyczny.

***

Programowanie w języku ABAP co prawda nie narzuca konieczności wykorzystania reguł programowania obiektowego, jednakże jest to rozwiązanie warte rozważenia, zwłaszcza w przypadku bardziej rozbudowanych programów. Odpowiednio przemyślane wykorzystanie obiektowości może uprościć zarządzanie kodem, a także pomóc powtórnym wykorzystaniu go w innych programach.