1. Présentation des interfaces
Aujourd'hui est votre journée pour la connaissance. Un autre sujet nouveau et intéressant est celui des interfaces.
Le concept d' interface est l'enfant des principes d'abstraction et de polymorphisme. Une interface est très similaire à une classe abstraite, dans laquelle toutes les méthodes sont abstraites. Elle se déclare de la même manière qu'une classe, mais on utilise le interface
mot clé.
interface Feline
{
void purr();
void meow();
void growl();
}
Voici quelques faits utiles sur les interfaces :
1. Déclarer une interface
interface Drawable
{
void draw();
}
interface HasValue
{
int getValue();
}
- Au lieu du
class
mot-clé, nous écrivonsinterface
. - Il ne contient que des méthodes abstraites (n'écrivez pas le
abstract
mot-clé) - En fait, les interfaces ont toutes
public
les méthodes
Une interface ne peut hériter que d'interfaces. Mais une interface peut avoir plusieurs parents. Une autre façon de dire cela est de dire que Java a plusieurs héritages d'interfaces. Exemples:
interface Piece extends Drawable, HasValue
{
int getX();
int getY();
}
3. Héritage des classes des interfaces
Une classe peut hériter de plusieurs interfaces (d'une seule classe). Cela se fait à l'aide du implements
mot-clé. Exemple:
abstract class ChessItem implements Drawable, HasValue
{
private int x, y, value;
public int getValue()
{
return value;
}
public int getX()
{
return x;
}
public int getY()
{
return y;
}
}
La classe ChessItem est déclarée abstraite : elle implémente toutes les méthodes héritées sauf draw
. En d'autres termes, la ChessItem
classe contient une méthode abstraite — draw()
.
La signification technique des mots-clés extends
et implements
est la même : les deux sont un héritage. La distinction a été faite pour améliorer la lisibilité du code. On dit aussi que les classes sont héritées (via extends
) et que les interfaces sont implémentées (via implements
)
4. variables
Voici la chose la plus importante : les variables ordinaires ne peuvent pas être déclarées dans les interfaces (bien que les variables statiques le puissent).
Mais pourquoi avons-nous besoin d'interfaces ? Quand sont-ils utilisés ? Les interfaces ont deux avantages importants par rapport aux classes :
2. Séparer la « description des méthodes » de leur mise en œuvre.
Auparavant, nous avons dit que si vous souhaitez autoriser les méthodes de votre classe à être appelées à partir d'autres classes, vos méthodes doivent être marquées avec le public
mot-clé. Si vous souhaitez que certaines de ces méthodes soient appelées uniquement depuis votre classe, vous devez les marquer avec le private
mot-clé . En d'autres termes, nous divisons les méthodes de la classe en deux catégories : "pour tout le monde à utiliser" et "uniquement pour notre propre usage".
Les interfaces contribuent à renforcer davantage cette division. Nous créerons une "classe spéciale pour tout le monde" ainsi qu'une deuxième classe "uniquement pour notre propre usage", qui héritera de la première classe. Voici à peu près à quoi cela ressemblerait:
Avant | Après |
---|---|
|
|
|
|
Nous avons divisé notre classe en deux : une interface et une classe qui hérite de l' interface . Et quel est l'avantage ici?
De nombreuses classes différentes peuvent implémenter (hériter) la même interface. Et chacun peut avoir son propre comportement. Par exemple, ArrayList
LinkedList
deux implémentations différentes de l' List
interface.
Ainsi, nous cachons non seulement les différentes implémentations, mais également la classe d'implémentation elle-même (puisque nous n'avons besoin que de l'interface dans le code). Cela nous permet d'être très flexibles : pendant que le programme s'exécute, nous pouvons remplacer un objet par un autre, en modifiant le comportement d'un objet sans affecter toutes les classes qui l'utilisent.
C'est une technique très puissante lorsqu'elle est combinée avec le polymorphisme. Pour l'instant, il est loin d'être évident pourquoi vous devriez faire cela. Vous devez d'abord rencontrer des programmes avec des dizaines ou des centaines de classes afin de comprendre que les interfaces peuvent vous rendre la vie tellement plus facile que sans elles.
3. Héritage multiple
En Java, toutes les classes ne peuvent avoir qu'une seule classe parent. Dans d'autres langages de programmation, les classes peuvent souvent avoir plusieurs classes parentes. Ceci est très pratique, mais pose également de nombreux problèmes.
Les créateurs de Java sont arrivés à un compromis : ils interdisaient l'héritage multiple de classes, mais autorisaient l'héritage multiple d'interfaces. Une interface peut avoir plusieurs interfaces parentes. Une classe peut avoir plusieurs interfaces parentes mais une seule classe parente.
Pourquoi ont-ils interdit l'héritage multiple de classes mais autorisé l'héritage multiple d'interfaces ? En raison du soi-disant problème d'héritage du diamant :
![Héritage multiple](https://cdn.codegym.cc/images/article/35e2cab5-b221-45ad-94f1-0ead41008739/1024.jpeg)
Lorsque la classe B hérite de la classe A, elle ne sait rien des classes C et D. Il utilise donc les variables de la classe A comme bon lui semble. La classe C fait la même chose : elle utilise les variables de la classe A, mais d'une manière différente. Et tout cela se traduit par un conflit dans la classe D.
Regardons l'exemple simple suivant. Disons que nous avons 3 classes :
class Data
{
protected int value;
}
class XCoordinate extends Data
{
public void setX (int x) { value = x;}
public int getX () { return value;}
}
class YCoordinate extends Data
{
public void setY (int y) { value = y;}
public int getY () { return value; }
}
La classe Data stocke la value
variable. Sa classe descendante XCoordinate utilise cette variable pour stocker la x
valeur, et la YCoordinate
classe descendante l'utilise pour stocker la y
valeur.
Et il fonctionne. Séparément. Mais si nous voulons que la classe XYCoordinates hérite à la fois des classes XCoordinate
et YCoordinate
, nous obtenons du code défectueux. Cette classe aura les méthodes de ses classes ancêtres, mais elles ne fonctionneront pas correctement, car elles ont le même value variable
.
Mais parce que les interfaces ne peuvent pas avoir de variables, elles ne peuvent pas avoir ce genre de conflit. En conséquence, l'héritage multiple d'interfaces est autorisé.
GO TO FULL VERSION