next up previous contents index
Nächste Seite: Arrays Aufwärts: Programmieren in Java Vorherige Seite: Vererbung   Inhalt   Index

Unterabschnitte

Interfaces

Klassen beschreiben Entwurf und Implementierung.




\psfig {figure=bilder/interfac.ps}




Interfaces enthalten



Beispiel:


   interface Verbose
   { int SILENT = 0;
     int VERBOSE = 1;
     void setVerbosity(int level);
   }



Anwendung:


   class VerboseThing extends Thing
     implements Verbose
   { ...
   }


Beispiel einer Interface-Anwendung

Aufgabe: Objekten von benutzerdefinierten Klassen sollen ein oder mehrere benannte Attribute zugeordnet werden.

z.B.


     ("Farbe", #ff00ff)
     ("transparent", false)




Zunächst: Der Typ Attr


public class Attr
{ private String name;
  private Object value;
  public Attr(String name)
  { this.name = name;
  }
  public Attr(String name, Object value)
  { this.name = name;
    this.value = value;
  }
  public String nameOf()
  { return name;
  }
  public Object valueOf()
  { return value;
  }
  public Object valueOf(Object newValue)
  { Object oldValue = value;
    value = newValue;
    return oldValue;
  }
}


Idee:

Ein Typ Attributed mit folgender Funktionalität:


   void add(Attr newAttr)
   Attr find(String AttrName)
   Attr remove(String AttrName)

Benutzertypen könnten diesen Typ Attributed erweitern und wären somit attributiert:


   class Figure extends Attributed
   { ...
   }

Problem: Einfacherbung in Java verbietet dies im Normalfall, da der Benutzertyp bereits eine Oberklasse hat.



Einziger Ausweg: Einbau der gewünschten Funktionalität in die Wurzelklasse Object. Geht nicht und ist auch nicht sinnvoll!

Lösung mit Interfaces:


   public interface Attributed
   { void add(Attr newAttr);
     Attr find(String attrName);
     Attr remove(String attrName);
   }

   class AttributedFigure extends WhatEver
     implements Attributed
   { ...
   }

Wir haben eine klare und einfache Lösung unseres Problems, können allerdings die Implementierung von Attributed nicht erben, sondern müssen sie selbst liefern.

zum Beispiel so:


import java.util.*;

public class AttributedImpl
   implements Attributed
{ protected Hashtable attrTable 
     = new Hashtable();

  public void add(Attr newAttr)
  { attrTable.put(newAttr.nameOf(), newAttr);
  }
  public Attr find(String name)
  { return (Attr) attrTable.get(name);
  }
  public Attr remove(String name)
  { return (Attr) attrTable.remove(name);
  }
}


Einfacherbung gegen Mehrfacherbung

Mehrfacherbung von Klassen führt bei rautenförmiger Hierarchiestruktur ( diamond inheritance)



\psfig {figure=bilder/diamond.ps}



zu Mehrdeutigkeiten.




Ursache für diese Mehrdeutigkeiten ist der Zugriff auf Implementierungsaspekte (Attribute)



Also: Einfacherbung für Klassen




Mehrfacherbung von Entwurfsaspekten macht keine Probleme



Also: Mehrfacherbung für Interfaces







   class AttributedFigure extends WhatEver
     implements Attributed, Verbose
   { ...
   }




Interface-Deklarationen

Ein Interface kann public- oder Paket-Sichtbarkeit haben (default). Bedeutung genau wie bei Klassen.




   public interface Verbose
   { ...
   }




Ein Interface ist abstrakt. Dies kann man durch abstract kennzeichnen, ist aber überflüssig.

Ein Interface kann ein oder mehrere Ober-Interfaces ( Superinterfaces) haben:




   interface X
     extends Y, Z
   { ...
   }

Die Superinterface-Beziehung darf natürlich weder direkt noch indirekt zyklisch sein.




Es gibt für Interfaces keine Analogie zur Wurzelklasse Object.

Interface-Elemente sind



Diese sind implizit public.

Weder public noch static und final für die Konstanten brauchen spezifiziert zu werden.




Konstanten in Interfaces

Die Konstanten müssen initialisiert werden.


  interface Verbose
   { int SILENT = 0;
     int VERBOSE = SILENT+1;
     void setVerbosity(int level);
   }

Initialisierungsausdrücke werden ausgewertet, wenn das Interface geladen wird. Es gelten die gleichen Regeln wie bei der Initialisierung von Klassenvariablen (Reihenfolge, kein this, etc., siehe Seite [*]).


Mehrdeutigkeiten bei Konstanten



\psfig {figure=bilder/ambig.ps}



D erbt ROT mehrmals: Kein Problem.



D erbt verschiedene Felder namens BLAU: Kein Problem, wenn D BLAU nicht benutzt, ansonsten Fehlermeldung.




Methoden in Interfaces

Implizit public und abstract. Verboten sind die Spezifikatoren static und final, wobei die Methode die eine Interface-Methode implementiert durchaus final sein darf.



Interface-Methoden können Methoden gleicher Signatur aus Ober-Interfaces überschreiben . Fehler, wenn Ergebnistyp verschieden.



Ein Interface kann 2 Methoden gleicher Signatur erben. Kein Problem, wenn der Ergebnistyp gleich ist.



Zwei Interface-Methoden mit gleichem Namen aber verschiedener Signatur sind überladen . Ergebnistyp spielt dabei keine Rolle.




Aus ``Streifzug durch Java'' (Seite [*]):

Interfaces erweitern die Möglichkeiten der Polymorphie:



Die Obertypen einer Klasse T umfassen

1.
den Typ, den T erweitert ( extends)
2.
die Typen, die T implementiert ( implements)
3.
die Obertypen der Typen aus [1.] und [2.].

Ein Objekt vom Typ T darf überall dort verwendet werden, wo Obertypen von T zulässig sind.

Beispiele für Interfaces der Java-Bibliothek

public interface Cloneable4



Klassen, die dieses Interface implementieren signalisieren der Methode Object.clone(), daß ihre Objekte kopiert werden können (elementweise Kopie).



clone()-Aufrufe für Objekte, deren Klassen dieses Interface nicht implementieren, führen zu einer CloneNotSupportedException.




public interface Runnable



Jede Klasse, deren Instanzen als Thread ausgeführt werden sollen, sollte Runnable implementieren.



\psfig {figure=bilder/methind.ps}


public abstract void run()

  When an object implementing interface
  Runnable is used to create a thread,
  starting the thread causes the
  object's run method to be called in
  that separately executing thread.



next up previous contents index
Nächste Seite: Arrays Aufwärts: Programmieren in Java Vorherige Seite: Vererbung   Inhalt   Index
Peter Pfahler, 1997