Java utilise une construction appelé interface qui fournit cette garantie. L’interface représente déclaration d’un ensemble des méthodes et des constantes. Les méthodes sont déclarées avec ses prototypes - son nom, le type de résultat, le nombre et les types des arguments, mais elles n’ont pas des corps. C'est une spécification qui ressemble beaucoup à une classe, mais elle ne peut pas avoir des instances (objets).
Pour définir une interface, on utilise la syntaxe :
[public] interface nom [extends
interface1,interface2,
...] {
modificateur type constante;
…
modificateur type methode( parametres );
…
}
Le but d’interface est de déclarer des méthodes qui doivent exister dans les classes qui les utilisent. On dit, qu'une classe qui hérite ces méthodes, implémente cette interface.
Comme pour les classes, chaque interface définit un type correspondant. Tout objet dont la classe implémente l'interface peut être considéré de ce type. Cela signifie qu'on peut écrire une méthode qui peut agir sur n'importe quel objet qui implémente cette interface – aucune importance ou ce trouve sa classe dans l'arbre d'héritage.
Important:
[public] class fille implements service {
...
}
La classe "fille" doit alors définir toutes les méthodes définies dans l’interface "service". Si, de plus, "service" est une interface étendant d’autres interfaces, la classe "fille" doit définir aussi bien toutes les méthodes des interfaces héritées.
Java ne permet pas l'héritage multiple - une
classe
ne peut hériter qu'une seule classe, mais par contre elle peut
implémenter
plusieurs interfaces. Comme ça le mécanisme des
interfaces
permet de contourner une des grandes restrictions dans le langage et de
satisfaire des besoins en matière d'héritage multiple.
//: Music.java
// Interfaces
import java.util.*;
interface Instrument { // On ne peut pas
avoir
des définitions des méthodes:
int k = 5; // static & final; constant
void play(); // Automatiquement public
void adjust();
}
interface Name {
String what();
}
class Wind implements Instrument,Name {
public void play() {
System.out.println("Wind.play()");
}
public String what() { return "Wind" + k+ "->"; }
public void adjust() {}
}
class Percussion implements Instrument,Name
{
public void play() {
System.out.println("Percussion.play()");
}
public String what() { return "Percussion" +k+ "->"; }
public void adjust() {}
}
class Stringed implements Instrument,Name {
public void play() {
System.out.println("Stringed.play()");
}
public String what() { return "Stringed" +k+ "->"; }
public void adjust() {}
}
class Brass extends Wind {
public void play() {
System.out.println("Brass.play()");
}
public void adjust() {
System.out.println("Brass.adjust()");
}
}
class Woodwind extends Wind {
public void play() {
System.out.println("Woodwind.play()");
}
public String what() { return "Woodwind" +k + "->"; }
}
public class Music {
// Doesn't care about type,
so new types
// added to the system
still work right:
static void tune(Instrument i) {
i.play();
}
static void tuneAll(Instrument[] e) {
for(int i = 0; i < e.length; i++)
tune(e[i]);
}
public static void main(String[] args) {
Instrument[] orchestra = new Instrument[5];
int i = 0;
// Upcasting en ajoutant des
éléments
au tableau:
orchestra[i++] = new Wind();
orchestra[i++] = new Percussion();
orchestra[i++] = new Stringed();
orchestra[i++] = new Brass();
orchestra[i++] = new Woodwind();
tuneAll(orchestra);
Name[] orchestra1 = new Name[5];
i=0;
orchestra1[i++] = new Wind();
orchestra1[i++] = new Percussion();
orchestra1[i++] = new Stringed();
orchestra1[i++] = new Brass();
orchestra1[i++] = new Woodwind();
for(i=0;i<5;i++) System.out.println(orchestra1[i].what());
}
}