
ABAP OO - Klasse und Vererbung
Im nächsten Teil der ABAP OO Grundlagen wollen wir dir den Grundbegriff der Klasse und deren Ausprägung zeigen, sowie es eigentlich mit der Vererbung läuft zwischen den einzelnen Objekten.
Inhaltsverzeichnis
Im letzten Artikel haben wir dir gezeigt, warum du Klassen einsetzen solltest und was die Besonderheiten von ABAP OO in SAP sind. Im heutigen Artikel wollen wir uns vor allem anschauen, wie eine Klasse aufgebaut ist und was man damit alles erreichen kann. Zudem schauen wir uns die erste einfach Vererbung an.
Einleitung
Warum ist es mittlerweile notwenig alle Bestandteile einer Klasse zu kennen und selbst definieren zu können? Über die Jahre hinweg war ABAP OO vor allem über den Formulareditor (SE24/SE80) verbreitet, damit hat das System bereits viele Schritte einer Klassendefinition für einen übernommen und man musste sich keine großen Gedanken mehr darum machen. Mit Eclipse ist dies nun wieder mehr in der Verantwortung des Entwicklers übergegangen, da es hier nur noch einen textbasierten Editor gibt und man die ganze Klasse auf einen Blick zur Bearbeitung hat.
Hinweis: Hierbei empfehlen wir auch klar die Arbeit über Eclipse, da du dadurch die komplette Klasse im Überblick hast, was dir eine klar höhere Entwicklungsgeschwinidgkeit bietet, da du dir das Navigieren durch die einzelnen Sichten sparst und alles auf einen Blick hast.
Klasse
Die Klassendefinition bildet die Hülle einer Klasse, in ihr kannst du verschiedene Objekte anlegen, die du je nach Sichtbarkeit nur innerhalb der Klasse verwenden kannst oder auch für Objekte außerhalb der Klasse zur Verfügung stellst. Die einfachste Form einer Klasse sieht daher wie folgt aus:
CLASS lcl_example DEFINITION.
ENDCLASS.
CLASS und ENDCLASS bilden den Anfang und das Ende der Klasse. Nach CLASS kommt der Name der Klasse unter der diese ansprechbar sein wird. Danach kommt die DEFINITION, die darauf hinweist, dass hier die Klassendefinition stattfindet. In ABAP ist die Definition einer Klasse und die eigentliche Implementierung immer voneinander getrennt. Die Implementierung würde dann dazu wie folgt aussehen:
CLASS lcl_example IMPLEMENTATION.
ENDCLASS.
Wenn du dann Methoden oder Attribute definieren willst, musst du zuerst die Sichtbarkeit für diese definieren. Mehr zur Sichtbarkeit erfährst du am Ende des Artikels. Zur Vereinfachung definieren wir erst einmal alles im öffentlichen Bereich, sodass es auch außerhalb der Klasse nutzbar ist.
CLASS lcl_example DEFINITION.
PUBLIC SECTION.
DATA:
md_status TYPE i,
md_text TYPE string.
METHODS:
get_final_text
RETURNING VALUE(rd_result) TYPE string.
ENDCLASS.
CLASS lcl_example IMPLEMENTATION.
METHOD get_final_text.
rd_result = |{ md_text }: { md_status }|.
ENDMETHOD.
ENDCLASS.
In die Implementierung der Klasse gehören nur die einzelnen Methoden mit ihrem Code, was die Übersichtlichkeit vereinfacht und die Schnittstelle und Daten von der eigentlichen Logik trennt. In vielen anderen Programmiersprachen gibt es dafür nur eine Stelle/eine Definition der Klasse.
Klasseneigenschaften
Bei der Definition von Klasse können auch noch verschiedene Eigenschaften definiert werden, die entsprechende Auswirkungen auf das Handling mit der Klasse haben. Diese Eigenschaften wollen wir in diesem Abschnitt kurz aufführen. Eigenschaften die hier noch nicht aufgeführt werden, folgenden in den weiteren Abschnitten oder anderen Artikel, wo wir noch einmal im Detail darauf eingehen wollen.
FINAL
Eine mit FINAL definierte Klasse besitzt Einschränkungen bei der Vererbung, von dieser Klasse darf nicht mehr geerbt werden. Sie bildet somit das Ende der Kette, weil sie zum Beispiel zu spezielle Implementierungen besitzt oder weil verhindert werden soll, dass Unterklassen mit anderer Logik implementiert werden.
CLASS lcl_example DEFINITION FINAL.
ENDCLASS.
CREATE
Der Zusatz schränkt ein wer den Konstruktor und damit die Instanziierung des Objekts durchführen darf. Eine öffentliche Erstellung ist normal und wird ohne Angabe als Standard genommen. In diesem Fall stellen wir die Erstellung auf Privat, damit darf nur die Klasse selbst die Erstellung einer Instanz durchführen oder einer der definierten Freunde.
CLASS lcl_example DEFINITION CREATE PRIVATE.
ENDCLASS.
FRIENDS
Definiert eine Liste von Klassen und Interfaces die von außen auch auf geschützte und private Methoden/Attribute zugreifen können. Dieses Konzept hebelt das Sichtbarkeitsprinzip aus und sollte nur mit Vorsicht und wenn du weißt was du tust, eingesetzt werden.
CLASS lcl_example DEFINITION FRIENDS lcl_other_class.
ENDCLASS.
Hinweis: Das Konzept von Freunden werden wir in einem späteren Artikel noch einmal im Detail beleuchten, da es zu einer Besonderheit von ABAP OO zählt.
Global/Lokal
Eine wichtige Unterscheidung ist noch die Verwendung der Klasse und wo du sie definierst. So gibt es lokale Klasse die innerhalb eines Report, eine Funktionsgruppe oder einer globalen Klasse definiert werden. Solche Klassen würden wir zum Beispiel mit "LCL_" (Locale class) beginnen und echten globalen Klassen die mit "ZCL_" (Class) beginnen. Bei der Definition gibt es daher noch ein paar kleine Unterschiede, dazu einmal die Gegenüberstellung.
CLASS zcl_example DEFINITION PUBLIC FINAL.
ENDCLASS.
CLASS lcl_example DEFINITION FINAL.
ENDCLASS.
Die globale Klasse erhält den Zusatz PUBLIC und definiert sie damit zur globalen Klasse. Eine globale Klasse ist im gesamten System bekannt und kann verwendet werden, ebenso wie ihr Komponenten die im öffentlichen Bereich definiert wurden.
Sichtbarkeit
Die Sichtbarkeit wird dann wichtig, wenn jemand mit deiner Klasse interagieren möchte. Wenn es um Sichtbarkeit in Klassen geht, dann gibt es hier drei Fälle:
- Public (Öffentlich) - Objekte in diesem Bereich sind für jeden von Außen zugänglich und können genutzt werden. Eine öffentliche Variable kann also direkt gelesen und geändert werden.
- Protected (Geschützt) - Der geschützte Bereich verhält sich wie der private Bereich, wird bei einer Vererbung aber auch für die erbende Klasse zur Verfügung gestellt.
- Private (Privat) - Das Objekt ist von außen nicht zugreifbar und kann nur innerhalb der aktuellen Klasse verwendet werden. Hierbei handelt es sich meist um Variablen und Methoden, die die öffentlichen Methoden untergliedern oder als Hilfsmethoden fungieren.
Innerhalb der Klasse gibt es daher die einzelnen Bereiche die definiert werden müssen, bevor du Methoden und Attribute zuordnen kannst. Die Bereiche werden wie folgt definiert:
CLASS lcl_example DEFINITION.
PUBLIC SECTION.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
Die Sichtbarkeit hat Einfluss auf die Vererbung und die Nutzung der Klasse. In diesen drei Bereichen können Attribute, Methoden, Typen und Konstanten liegen, für die genau diese Regeln gelten. Wenn du ein Objekt erstellst, verwendest du im Normalfall nur Public und Private, wenn du Eigenschaften vererben möchtest, werden diese dann meistens von Private auf Protected gestellt.
Vererbung
Die Vererbung sorgt für eine Wiederverwendung und Erweiterung von Klassen in einem definierten Rahmen. Damit kannst du eine Klasse weiter spezialisieren und neue Features implementieren. Bei der Vererbung hat die Sichtbarkeit auch einen großen Einfluss auf das, was an die Unterklasse weitergegeben wird. Daher solltest du dir merken, dass öffentliche und geschützte Eigenschaften an die erbende Klasse weitergegeben werden.
Dazu definieren wir eine lokale Klasse LCL_ANIMAL die ein abstraktes Tier darstellen soll. Es wird die Anzahl der Arme und Beine intern gesichert und es gibt als Schnittstelle jeweils eine Methode um die Werte des Tiers zu ermitteln.
CLASS lcl_animal DEFINITION.
PUBLIC SECTION.
METHODS:
get_number_of_arms
RETURNING VALUE(rd_result) TYPE i,
get_number_of_legs
RETURNING VALUE(rd_result) TYPE i.
PROTECTED SECTION.
DATA:
md_arms TYPE i,
md_legs TYPE i.
PRIVATE SECTION.
ENDCLASS.
CLASS lcl_animal IMPLEMENTATION.
METHOD get_number_of_arms.
rd_result = md_arms.
ENDMETHOD.
METHOD get_number_of_legs.
rd_result = md_legs.
ENDMETHOD.
ENDCLASS.
Die Attribute haben wir dabei im geschützten Bereich angelegt, damit niemand von Außen darauf zugreifen kann oder den Inhalt ändern kann. Nun möchten wir eine Klasse definieren die dieses Grundgerüst nutzt und ein spezifiziertes Tier implementiert.
CLASS lcl_cat DEFINITION INHERITING FROM lcl_animal.
PUBLIC SECTION.
METHODS:
constructor.
ENDCLASS.
CLASS lcl_animal IMPLEMENTATION.
METHOD constructor.
md_legs = 4.
ENDMETHOD.
ENDCLASS.
Mit INHERITING FROM sagst du während der Klassendefinition, dass du von einer anderen Klasse erben möchtest. In diesem Fall erbt die Klasse Katze von dem Tier. Wir definieren noch einen Konstruktor der uns die Werte vorbelegt, sobald eine neue Instanz der Klasse angelegt wird. Auf die Konstruktoren werden wir im nächsten Artikel noch weiter eingehen. Nun kannst du diese Klasse ebenfalls verwenden:
" ld_legs = 0
DATA(lo_animal) = NEW lcl_animal( ).
DATA(ld_legs) = lo_animal->get_number_of_legs( ).
" ld_legs = 4
DATA(lo_cat) = NEW lcl_cat( ).
ld_legs = lo_cat->get_number_of_legs( ).
Du siehst an diesem Beispiel, dass beide Methoden und die Attribute an die Klasse lcl_cat vererbt werden und dort auch genutzt werden können. Damit kannst du auch die Klasse lcl_animal für die Implementierung anderer Klassen nutzen. Wenn du dann später einmal die Klasse erweitern willst um zu sätzliche Attribute, dann musst du nur noch die Oberklasse lcl_animal anpassen und alle erbenden Klassen erhalten automatisch die neuen Eigenschaften und Fähigkeiten.
Fazit
Wir hoffen, wir konnten dir mit diesem Artikel einen tieferen Einblick in die allgemeinen Klasse und das Thema Vererbung geben. In den folgenden Artikeln werden wir weiter in die Tiefe der Entwicklung gehen und auch einmal über das Design von Objekten sprechen.