Anfang des Inhaltsbereichs

Interfaces Dokument im Navigationsbaum lokalisieren

Klassen, deren Objektinstanzen, und der Zugriff über Referenzvariablen bilden die Grundlage von ABAP Objects. Allein mit diesen Mitteln ist es schon möglich typische Business-Anwendungen mit Objekten wie Kunde, Auftrag, Position, Rechnung usw., zu modellieren und mit ABAP Objects zu implementieren.

Es kommt aber oft vor, daß ähnliche Klassen eine gleichartige Funktionalität zur Verfügung stellen müssen, die zwar unterschiedlich in den einzelnen Klassen kodiert ist, aber vom Benutzer mit der gleichen Schnittstelle aufgerufen werden soll. Beispielsweise können wir uns die ähnlichen Klassen Sparkonto und Girokonto vorstellen, die beide eine Methode zur Berechnung des Jahresabschlusses anbieten. Schnittstelle und Name der Methode sind gleich, die eigentliche Implementierung ist jedoch unterschiedlich. Weiterhin möchte der Benutzer dieser Klassen, bzw. deren Instanzen, den Jahresabschluß für alle Konten durchführen, ohne sich darum zu kümmern, welche Kontoart vorliegt.

Um dies zu ermöglichen stellt ABAP Objects sogenannte Interfaces zur Verfügung. Interfaces sind selbständige Konstrukte, die es erlauben, durch ihre Implementierung in Klassen die klassenspezifischen Schnittstellen zu erweitern. Die klassenspezifischen Schnittstellen einer Klasse werden durch die Komponenten der Klasse und ihre Sichtbarkeitsbereiche definiert. Die öffentlichen Komponenten bilden die öffentliche Schnittstelle der Klasse, da alle Attribute und Methodenparameter von jedem Verwender adressierbar sind.

Interfaces erweitern die öffentlichen Komponenten von Klassen um Interfacekomponenten und ermöglichen es somit, unterschiedliche Klassen auch über verschiedene Vererbungsbäume hinweg über identische Schnittstellen anzusprechen. Sogenannte Interfacereferenzen ermöglichen es einem Verwender verschiedene Klassen völlig gleichartig anzusprechen und zu verwenden. Interfaces sind somit neben der Vererbung eine der Grundlagen für die Polymorphie von Klassen, da eine Methode eines Interfaces sich in unterschiedlichen Klassen unterschiedlich verhalten kann.

Definition von Interfaces

Die Definition von Interfaces erfolgt wie die von Klassen global im R/3-Repository oder lokal in einem ABAP-Programm. Zur Definition globaler Interfaces, siehe die Dokumentation des Strukturlink Class Builders der ABAP Workbench. Die Definition eines lokalen Interfaces <intf> wird durch die Anweisungen

INTERFACE <intf>.

...

ENDINTERFACE.

eingeschlossen. Die Definition enthält die Deklaration aller Komponenten (Attribute, Methoden, Ereignisse) des Interfaces. In Interfaces können die gleichen Komponenten definiert werden, wie in Klassen. Die Komponenten von Interfaces müssen nicht explizit einem Sichtbarkeitsbereich zugeordnet werden, da die Komponenten von Interfaces bei ihrer Implementierung im öffentlichen Bereich der Klasse immer die öffentlichen Komponenten der Klasse erweitern. Für Interfaces gibt es keinen Implementierungsteil, da die Methoden eines Interface in den Klassen implementiert werden müssen, die das Interface implementieren

Implementierung von Interfaces

Im Unterschied zu Klassen gibt es keine Instanzen von Interfaces. Stattdessen werden Interfaces von Klassen implementiert. Zur Implementierung von Interfaces in einer Klasse dient die Anweisung

INTERFACES <intf>.

im Deklarationsteil der Klasse. Diese Anweisung darf nur im öffentlichen Sichtbarkeitsbereich der Klasse, also hinter PUBLIC SECTION aufgeführt werden.

Bei der Implementierung eines Interfaces in einer Klasse werden die Komponenten des öffentlichen Sichtbarkeitsbereichs der Klasse um die Komponenten des implementierten Interfaces erweitert. Eine Komponente <icomp> eines implementierten Interfaces <intf> wird zu einer vollwertigen Komponente der Klasse und unter dem Namen <intf~icomp> angesprochen.

Die Klasse muß das Verhalten der Methoden aller implementierten Interfaces selbst implementieren. Der Implementierungsteil der Klasse muß also für jede Interfacemethode <imeth> eine Methodenimplementierung enthalten:

METHOD <intf~imeth>.

...

ENDMETHOD.

Ein Interface kann von verschiedenen Klassen implementiert werden. Jede dieser Klassen erhält dadurch die gleiche Komponentenerweiterung. Die Methoden des Interfaces können in jeder Klasse unterschiedlich implementiert werden. Dabei sollte jede Klasse die Semantik des Interfaces bewahren. Eine Methodenimplementierung soll genau die Funktionalität liefern, die das Interface erfordert.

Interfaces ermöglichen es, unterschiedliche Klassen über Interfacereferenzen gleichartig zu verwenden (Polymorphie). Interfaces, die beispielsweise in verschiedenen Klassen implementiert werden, erweitern die öffentlichen Schnittstellen dieser Klassen um die gleichen Komponenten. Falls eine Klasse außer Interfaces keine klassenspezifischen Komponenten im öffentlichen Bereich enthält, bestimmen die Interfaces die gesamte öffentliche Schnittstelle der Klasse.

Interfacereferenzen

Referenzvariablen dienen dem Zugriff auf Objekte (siehe Arbeiten mit Objekten). Statt Referenzvariablen mit Bezug auf eine Klasse anzulegen, können Referenzvariablen auch mit Bezug auf ein Interface typisiert werden. Solche Referenzvariablen können Referenzen auf Objekte von Klassen enthalten, die das entsprechende Interface implementieren.

Interfacereferenzen werden mit dem Zusatz TYPE REF TO <intf> der TYPES- oder DATA- Anweisung definiert. Dabei ist <intf> ein an der Deklarationsstelle bekanntes Interface. Eine Referenzvariable vom Typ Interfacereferenz heißt Interfacereferenzvariable oder ebenfalls kurz Interfacereferenz.

Eine Interfacereferenz <iref> ermöglicht es einem Verwender, über <iref>-><icomp> auf alle ihm sichtbaren Interfacekomponenten <icomp> des Objekts zuzugreifen, auf die die Objektreferenz zeigt. Der Verwender hat über diese Referenzvariable also Zugriff auf genau die Komponenten eines Objekts, die durch die Implementierung des Interfaces zu den klassenspezifischen Komponenten hinzukamen.

Zugriff auf Objekte über Interfacereferenzen

Wenn eine Klasse <class> ein Interface <intf> implementiert, kann durch eine Zuweisung zwischen der Klassenreferenzvariable <cref> und einer Interfacereferenzvariable <iref>

<iref> = <cref>

die Interfacereferenz in <iref> auf das gleiche Objekt zeigen, wie die Klassenreferenz in <cref>.

Wenn eine Klasse <class> ein Interface <intf> implementiert, muß nicht unbedingt zuerst eine Klassenreferenzvariable <cref> mit Bezug auf die Klasse deklariert werden, um ein Objekt einer Klasse <class> zu erzeugen. Statt dessen kann in der Anweisung CREATE OBJECT der TYPE-Zusatz verwendet werden, um eine Instanz der Klasse mit einer Interfacereferenzvariablen zu erzeigen:

CREATE OBJECT <iref> TYPE <class>.

Es wird eine Instanz der Klasse <class> erzeugt, auf welche die Referenz in <iref> zeigt.

Wenn das Interface <intf> ein Instanzattribut <attr> und eine Instanzmethode <meth> enthält, können diese Interfacekomponenten des Objekts wie folgt adressiert werden:

Über die Klassenreferenzvariable <cref>:

Über die Interfacereferenzvariable <iref>:

Bei den statischen Komponenten von Interfaces kann nur für Konstanten der Name des Interfaces für den Zugriff verwendet werden.

Zugriff auf eine Konstante <const>: < intf>=><const>

Auf alle übrigen statischen Komponenten eines Interfaces kann außer über Objektreferenzen nur über Klassen <class> zugegriffen werden, die das Interface implementieren:

Zugriff auf ein statisches Attribut <attr>: < class>=><intf~attr>

Aufruf einer statischen Methode <meth>: CALL METHOD <class>=><intf~meth>

Schachtelung von Interfaces

Interfaces können geschachtelt werden. Ein Interface kann ein oder mehrere Interfaces als Komponenten enthalten, die selbst wieder Interfaces enthalten können. Ein Interface, das ein anderes Interface enthält, wird geschachteltes oder zusammengesetztes Interface genannt. Ein Interface, das in einem Interface geschachtelt ist, heißt Komponenten-Interface. Ein Interface, das keine geschachtelten Interfaces enthält heißt elementares Interface.

Sämtliche Interface-Komponenten eines geschachtelten Interfaces liegen auf einer Ebene. Wenn ein geschachteltes Interface i3 Interface-Komponenten i2 enthält, die selber geschachtelt sind, werden deren Interface-Komponenten i1 zu Interface-Komponenten von i3. Dabei enthält ein geschachteltes Interface jede Interface-Komponente genau einmal. Auch wenn ein Komponenten-Interface ein weiteres mal als Komponente eines anderen Komponenten-Interfaces eingebaut wird, ist es trotzdem nur ein einziges mal vorhanden.

Zur Schachtelung von Interfaces dient die Anweisung INTERFACES innerhalb einer Interface-Definition:

INTERFACE i3.
  ...
  INTERFACES: i1, i2 ...
  ...
ENDINTERFACE.

Hier besteht das Interface i3 aus seinen Komponenten und aus den Interfaces i1 und i2. Die Komponenten der Komponenten-Interfaces sind im geschachtelten Interface nicht direkt sichtbar. Innerhalb obiger Definition von i3 sind Ausdrücke wie i1~comp oder i2~comp mit Ausnahme der ALIAS-Anweisung nicht möglich.

Um die Komponenten von Komponenten-Interfaces zu verwenden, gibt es folgende Möglichkeiten:

Verwendung von Alias-Namen

Innerhalb von Interfacedefinitionen können mit der ALIAS-Anweisung lias-Namen den Komponenten von Komponenten-Interfaces zugewiesen werden und diese dadurch innerhalb der Interfacedefinition sichtbar gemacht werden:

INTERFACE i2.
  ...
  INTERFACES i1.
  ALIASES alias21 FOR i1~comp1.
  ...
ENDINTERFACE.

INTERFACE i3.
  ...
  INTERFACES i2.
  ALIASES alias31 FOR i2~alias21.
  ALIASES alias32 FOR i2~comp2.
  ...
ENDINTERFACE.

Zuweisung von Interfacereferenzen

Interfacereferenzen, die mit Bezug auf ein geschachteltes Interface typisiert sind, können Interfacereferenzen zugewiesen werden, die mit Bezug auf eines der Komponenten-Interfaces typisiert sind. Über letztere können die Komponenten der Komponenten-Interfaces angesprochen werden:

INTERFACE i2.
...
INTERFACES i1.
...
ENDINTERFACE.

INTERFACE i3.
...
INTERFACES i2.
...
ENDINTERFACE.

DATA: iref1 TYPE REF TO i1,
iref2 TYPE REF TO i2,
iref3 TYPE REF TO i3.

iref2 = iref3.
iref1 = iref2.

... iref1->comp1 ...
... iref2->comp2 ...

Nicht möglich sind aber folgende Ausdrücke:

... iref2->i1~comp1 ...
... iref3->i2~comp2 ...

Implementierung geschachtelter Interfaces in Klassen

Wenn ein geschachteltes Interface in einer Klasse implementiert wird, werden sämtliche beteiligten Interfaces unabhängig von ihrer Schachtelungshierarchie gleichberechtigt nebeneinander in der Klasse implementiert und die Klasse muß sämtliche Methoden implementieren.

INTERFACE i2.
...
INTERFACES i1.
...
ENDINTERFACE.

INTERFACE i3.
...
INTERFACES i2.
...
ENDINTERFACE.

CLASS class DEFINITION.
...
INTERFACES i3.
...
ENDCLASS.

CLASS class IMPLEMENTATION.
...
METHOD i1~meth.
...
ENDMETHOD.
...
ENDCLASS.

Verwendung:

DATA: cref TYPE REF TO class.

... cref->i1~comp1 ...
... cref->i2~comp2 ...
... cref->i3~comp3 ...

Geschachtelte Ausdrücke wie cref->i3~i2~comp2 oder cref->i3~i2~i3~comp3 sind nicht möglich. Die Schachtelungshierarchie spielt nur bei der Zuweisung zwischen Interfacereferenzen eine Rolle. Klassenreferenzen, für Klassen, die ein geschachteltes Interface implementieren, können allen Interfacereferenzen zugewiesen werden, die mit Bezug auf eine zugehörige Interface-Komponente typisiert sind. Die Interfacereferenzen kennen in der Klasse jeweils nur die Komponenten ihres Interfaces.

Interfaces und Vererbung

Bei Interfaces beruht die Polymorphie darauf, daß jede Klasse, die ein Interface implementiert, dessen Methoden anders implementieren kann. Nach außen sehen aber alle Interface-Komponenten gleich aus, weshalb Interfacereferenzen auf Objekte aller Klassen zeigen können, die das zugehörige Interface implementieren.

Das Interface-Konzept ist zum Konzept der Vererbung vollständig orthogonal. In den Klassen eines Vererbungsbaums können beliebig viele Interfaces implementiert werden, wobei jedes Interface aber nur einmal pro Vererbungsbaum implementiert werden kann. Dadurch hat jede Interface-Komponente über den gesamten Vererbungsbaum einen eindeutigen Namen intf~icomp und ist ab der Klasse, die das Interface implementiert, in allen Unterklassen enthalten. Interfacereferenzen, die auf eine Klasse eines Vererbungsbaums zeigen können, können auch auf sämtliche Unterklassen zeigen. Interfacemethoden sind nach ihrer Implementierung vollwertige Komponenten einer Klasse und können in Unterklassen redefiniert werden. Interfacemethoden können aber in der Definition des Interfaces nicht als abstrakt oder final deklariert werden.

Siehe auch

Übersichtsgrafiken

Einführendes Beispiel zu Interfaces

Ende des Inhaltsbereichs