Schnittstellen

Eine Schnittstelle (Englisch „interface“) ist eine Sammlung von Methodendeklarationen, über die nicht miteinander verwandte Objekte miteinander kommunizieren können. Beispielsweise definiert ActionScript 3.0 die IEventDispatcher-Schnittstelle, die Methodendeklarationen enthält, die eine Klasse zur Verarbeitung von Ereignisobjekten verwenden kann. Die IEventDispatcher-Schnittstelle ist ein Standardverfahren für Objekte, einander Ereignisobjekte zu übergeben. Der folgende Code zeigt die Definition der IEventDispatcher-Schnittstelle:

public interface IEventDispatcher 
{ 
    function addEventListener(type:String, listener:Function,  
            useCapture:Boolean=false, priority:int=0, 
            useWeakReference:Boolean = false):void; 
    function removeEventListener(type:String, listener:Function,  
            useCapture:Boolean=false):void; 
    function dispatchEvent(event:Event):Boolean; 
    function hasEventListener(type:String):Boolean; 
    function willTrigger(type:String):Boolean; 
}

Schnittstellen basieren auf dem Unterschied zwischen der Schnittstelle einer Methode und ihrer Implementation. Die Schnittstelle einer Methode umfasst alle Informationen, die zum Aufrufen dieser Methode notwendig sind, einschließlich des Namens der Methode, aller ihrer Parameter sowie ihres Rückgabetyps. Die Implementation einer Methode umfasst nicht nur die Schnittstelleninformationen, sondern auch die ausführbaren Anweisungen, die das Verhalten der Methode ausführen. Eine Schnittstellendefinition enthält nur die Schnittstellen der Methode. Jede Klasse, welche die Schnittstelle implementiert, ist für die Definition der Methodenimplementationen selbst verantwortlich.

In ActionScript 3.0 implementiert die EventDispatcher-Klasse die IEventDispatcher-Schnittstelle, indem sie alle IEventDispatcher-Schnittstellenmethoden definiert und jeder Methode die Methodenrümpfe hinzufügt. Der folgende Code ist ein Auszug der EventDispatcher-Klassendefinition:

public class EventDispatcher implements IEventDispatcher 
{ 
    function dispatchEvent(event:Event):Boolean 
    { 
        /* implementation statements */ 
    } 
 
    ... 
}

Die IEventDispatcher-Schnittstelle dient als Protokoll, das die EventDispatcher-Instanzen verwenden, um Ereignisobjekte zu verarbeiten und an andere Objekte zu übergeben, die ebenfalls von der IEventDispatcher-Schnittstelle implementiert werden.

Anders ausgedrückt könnte man über eine Schnittstelle auch sagen, dass sie einen Datentyp genauso wie eine Klasse definiert. Entsprechend kann eine Schnittstelle wie eine Klasse als Typanmerkung verwendet werden. Als Datentyp kann eine Schnittstelle auch mit Operatoren wie is und as verwendet werden, die einen Datentyp benötigen. Im Gegensatz zu einer Klasse kann eine Schnittstelle jedoch nicht instanziiert werden. Dieser Unterschied hat dazu geführt, dass sich viele Programmierer Schnittstellen als abstrakte Datentypen und Klassen als konkrete Datentypen vorstellen.

Definieren einer Schnittstelle

Die Struktur einer Schnittstellendefinition ähnelt der einer Klassendefinition, außer dass eine Schnittstelle nur Methoden ohne Methodenrümpfe enthalten kann. Schnittstellen können get- und set-Methoden, jedoch keine Variablen oder Konstanten enthalten. Zur Definition einer Schnittstelle verwenden Sie das Schlüsselwort interface. Beispielsweise handelt es sich bei der Schnittstelle „IExternalizable“ um einen Teil des flash.utils-Pakets in ActionScript 3.0. Die IExternalizable-Schnittstelle definiert ein Protokoll zur Serialisierung eines Objekts. Dies bedeutet die Schnittstelle wandelt ein Objekt in ein Format um, das zur Speicherung auf einem Gerät oder für den Transport über ein Netzwerk geeignet ist.

public interface IExternalizable 
{ 
    function writeExternal(output:IDataOutput):void; 
    function readExternal(input:IDataInput):void; 
}

Die IExternalizable-Schnittstelle wird mit dem public-Zugriffskontrollmodifizierer deklariert. Schnittstellendefinitionen können nur über die Zugriffskontrollbezeichner public und internal modifiziert werden. Die Methodendeklarationen in einer Schnittstellendefinition können keine Zugriffskontrollbezeichner enthalten.

ActionScript 3.0 folgt der Konvention, den Schnittstellennamen mit einem Großbuchstaben I zu beginnen; Sie können jedoch auch jeden anderen zulässigen Bezeichner als Schnittstellennamen verwenden. Schnittstellendefinitionen werden häufig auf der obersten Ebene eines Pakets platziert. Schnittstellendefinitionen können nicht in einer Klassendefinition oder einer anderen Schnittstellendefinition platziert werden.

Schnittstellen können eine oder mehrere andere Schnittstellen erweitern. Beispielsweise erweitert die folgende IExample-Schnittstelle die IExternalizable-Schnittstelle:

public interface IExample extends IExternalizable 
{ 
    function extra():void; 
}

Jede Klasse, welche die IExample-Schnittstelle implementiert, muss Implementationen nicht nur für die extra()-Methode, sondern auch für die von der IExternalizable-Schnittstelle geerbten Methoden writeExternal() und readExternal() umfassen.

Implementieren einer Schnittstelle in einer Klasse

Eine Klasse ist das einzige Sprachelemente in ActionScript 3.0, das eine Schnittstelle implementieren kann. Verwenden Sie das Schlüsselwort implements in einer Klassendeklaration, um eine oder mehrere Schnittstellen zu implementieren. Im folgenden Codebeispiel werden die beiden Schnittstellen „IAlpha“ und „IBeta“ sowie eine Klasse Alpha definiert, die beide Schnittstellen implementiert:

interface IAlpha 
{ 
    function foo(str:String):String; 
} 
 
interface IBeta 
{ 
    function bar():void; 
} 
 
class Alpha implements IAlpha, IBeta 
{ 
    public function foo(param:String):String {} 
    public function bar():void {} 
}

In einer Klasse, die eine Schnittstelle implementiert, müssen implementierte Methoden:

  • Den Zugriffskontrollbezeichner public verwenden.

  • Den gleichen Namen wie die Schnittstellenmethode verwenden.

  • Die gleiche Anzahl an Parametern aufweisen, jeder mit dem Datentyp, der dem Datentyp der Parameter in der Schnittstellenmethode entspricht.

  • Den gleichen Rückgabetyp verwenden.

    public function foo(param:String):String {}

Bei der Benennung der Parameter der von Ihnen implementierten Methoden haben Sie eine gewisse Flexibilität. Obwohl Anzahl der Parameter und Datentyp jedes Parameters in der implementierten Methode denen der Schnittstellenmethode entsprechen müssen, müssen die Parameternamen nicht übereinstimmen. So lautet der Name des Parameters der Methode Alpha.foo() aus dem vorangegangenen Beispiel param:

In der Schnittstellenmethode IAlpha.foo() lautet der Name des Parameters hingegen str:

function foo(str:String):String;

Auch bei den Standard-Parameterwerten haben Sie eine gewisse Flexibilität. Eine Schnittstellendefinition kann Funktionsdeklarationen mit Standard-Parameterwerten enthalten. Eine Methode, die eine solche Funktionsdeklaration implementiert, muss einen Standard-Parameterwert aufweisen, der Mitglied des gleichen Datentyps wie der in der Schnittstellendefinition angegebene Wert ist, der tatsächliche Wert muss jedoch nicht übereinstimmen. Beispielsweise definiert der folgende Code eine Schnittstelle, die eine Methode mit einem Standard-Parameterwert 3 enthält:

interface IGamma 
{ 
    function doSomething(param:int = 3):void; 
}

Die folgende Klassendefinition implementiert die IGamma-Schnittstelle, verwendet jedoch einen anderen Standard-Parameterwert:

class Gamma implements IGamma 
{ 
    public function doSomething(param:int = 4):void {} 
}

Der Grund für diese Flexibilität liegt darin, dass die Datentypkompatibilität mit den Regeln zur Implementierung einer Schnittstelle sichergestellt wird und hierfür keine identischen Parameternamen und Standard-Parameterwerte erforderlich sind.