web-dev-qa-db-fra.com

Héritage multiple sur interfaces Java

Je pensais que l'héritage multiple était toujours illégal en Java, mais ce code compile:

public interface A {
  void a();
}

public interface B {
  void b();
}

public interface AB extends A, B {
}

Une interface vide telle que AB serait-elle considérée comme une mauvaise pratique? Existe-t-il un moyen d'obtenir quelque chose de similaire en évitant l'interface vide (en utilisant des génériques ou autrement)?

Remarque: je ne vous demande pas comment simuler un héritage multiple via des interfaces. Je réalise que je pourrais faire ce qui suit:

public class AbImpl implements A, B {
  public void a() {}
  public void b() {}
}

Pour diverses raisons, j'ai besoin d'une interface qui utilise les deux méthodes.

28
Jacob Wallace

L'héritage multiple de implémentations n'est pas autorisé. Les composants peuvent cependant hériter de plusieurs interfaces.

L'héritage de plusieurs interfaces ne pose pas de problème, car vous définissez simplement de nouvelles signatures de méthodes à implémenter. C’est l’héritage de multiples copies de fonctionnalités qui est généralement considéré comme source de problèmes, ou tout au moins de confusion (par exemple, le diamant de la mort ).

27
Brian Agnew

Une interface peut étendre une ou plusieurs autres interfaces. Vous pouvez également implémenter plusieurs interfaces dans vos classes. C'est légal parce que l'interface n'est que contrat - il n'y a pas de mise en œuvre. Vous définissez simplement un contrat pour ce qu'une classe est capable de faire, sans rien dire de la façon dont la classe va le faire.

8
Maciej Ziarko

Implémenter des interfaces n'est pas un "héritage", c'est-à-dire lorsque vous expand une classe.

L'implémentation d'interfaces est utilisée pour déclarer qu'une classe "ressemble" à quelque chose, alors que l'extension de classes est utilisée pour déclarer qu'une classe "est un" quelque chose.

C'est bien de "ressembler" à plusieurs choses, mais pas de "être" plusieurs choses.


Il n’ya rien de mal à avoir des interfaces vides qui étendent plusieurs interfaces afin de rassembler un ensemble d’interfaces en une seule interface afin de véhiculer une API plus large, mais réutilisée.

4
Bohemian

Dans cette question connexe , Jay fournit une réponse à cette question. La différence est de spécifier l'implémentation par rapport à l'interface. 

Le problème avec l'implémentation ne se produit que lorsque deux fonctions ont le même nom. En effet, la question "Quelle implémentation de f() est-ce que je l'utilise?" avec plusieurs implémentations.

Le problème ne se produit pas avec deux interfaces du même nom de fonction car il n'est pas nécessaire de faire cette sélection. Au lieu de cela, vous devez simplement implémenter votre propre version de la fonction disponible. 

A titre d'exemple, nous pouvons regarder une contrepartie qui autorise l'héritage multiple - C++ . Ce lien explique bien les choses et fournit des exemples de code/image. Une chose à noter est que, puisque vous devez de toute façon définir explicitement la classe à laquelle une fonction appartient, vous pouvez facilement atténuer le problème en C++.

Cependant, en Java, nous n’avons vraiment jamais à le faire (car il n’existe que des méthodes qui sont attachées à des objets, si vous voulez), ce qui fait que l’appel n’a pas de méthode. Les seules options possibles pour faire référence à une classe parente sont le mot clé super ou la fonction static. En conséquence, il n'y aurait pas d'option claire pour résoudre ce problème en Java, à moins de modifications supplémentaires du système, pour un gain minime.

0
Doug Swain