D'après ce que je comprends, si vous implémentez une interface en java, les méthodes spécifiées dans cette interface doivent être utilisées par les sous-classes implémentant ladite interface.
J'ai remarqué que dans certaines interfaces telles que l'interface Collection, il existe des méthodes qui sont commentées comme facultatives, mais qu'est-ce que cela signifie exactement? Cela m'a un peu gêné car je pensais que toutes les méthodes spécifiées dans l'interface seraient nécessaires?
Réponses:
Il semble y avoir énormément de confusion dans les réponses ici.
Le langage Java exige que chaque méthode d'une interface soit implémentée par chaque implémentation de cette interface. Période. Il n'y a pas d'exceptions à cette règle. Dire "Les collections sont une exception" suggère une compréhension très floue de ce qui se passe réellement ici.
Il est important de réaliser qu'il existe en quelque sorte deux niveaux de conformité à une interface:
Ce que le langage Java peut vérifier. Cela se résume à peu près à: y a-t-il une implémentation pour chacune des méthodes?
Remplir réellement le contrat. Autrement dit, l'implémentation fait-elle ce que la documentation de l'interface dit qu'elle devrait?
Des interfaces bien écrites comprendront une documentation expliquant exactement ce qui est attendu des implémentations. Votre compilateur ne peut pas vérifier cela pour vous. Vous devez lire les documents et faire ce qu'ils disent. Si vous ne faites pas ce que dit le contrat, vous aurez une implémentation de l'interface en ce qui concerne le compilateur , mais ce sera une implémentation défectueuse / invalide.
Lors de la conception de l'API Collections, Joshua Bloch a décidé qu'au lieu d'avoir des interfaces très fines pour distinguer les différentes variantes de collections (par exemple: lisibles, inscriptibles, à accès aléatoire, etc.), il n'aurait qu'un ensemble d'interfaces très grossier, principalement
Collection
,List
,Set
etMap
, puis documenter certaines opérations comme « facultatif ». C'était pour éviter l'explosion combinatoire qui résulterait des interfaces à grain fin. À partir de la FAQ de conception d'API de collections Java :Lorsque les méthodes de l'API Collections sont documentées comme étant des "opérations facultatives", cela ne signifie pas que vous pouvez simplement laisser l'implémentation de la méthode dans l'implémentation, ni que vous pouvez utiliser un corps de méthode vide (d'une part, beaucoup de ils doivent renvoyer un résultat). Cela signifie plutôt qu'un choix d'implémentation valide (qui est toujours conforme au contrat) consiste à lancer un
UnsupportedOperationException
.Notez que parce que
UnsupportedOperationException
c'est un,RuntimeException
vous pouvez le lancer à partir de n'importe quelle implémentation de méthode, en ce qui concerne le compilateur. Par exemple, vous pouvez le lancer à partir d'une implémentation deCollection.size()
. Cependant, une telle mise en œuvre violerait le contrat car la documentationCollection.size()
ne dit pas que cela est autorisé.A part: L'approche utilisée par l'API Collections de Java est quelque peu controversée (probablement moins maintenant que lorsqu'elle a été introduite pour la première fois). Dans un monde parfait, les interfaces n'auraient pas d'opérations optionnelles, et des interfaces à grain fin seraient à la place utilisées. Le problème est que Java ne prend en charge ni les types structurels inférés ni les types d'intersection, c'est pourquoi tenter de faire les choses de la «bonne manière» finit par devenir extrêmement compliqué dans le cas des collections.
la source
There are no exceptions to this rule
. Vous vous demandez pourquoi cette réponse n'est pas marquée comme acceptée. D'autres sont bons mais vous avez donné plus qu'assez.Foo
qui n'implémente pasRunnable
avec la méthode publiquevoid run()
. Maintenant, créez une classeBar
quiextends Foo
etimplements Runnable
sans surchargerrun
. Il implémente toujours la méthode, bien qu'indirectement. De même, une implémentation de méthode par défaut est toujours une implémentation.remove
a reçu une implémentation par défaut. Si vous ne l'implémentez pas, votre classe obtient l'implémentation par défaut. Les deux autres méthodes que vous mentionnez n'ont pas d'implémentations par défaut.Afin de compiler une classe d'implémentation (non abstraite) pour une interface, toutes les méthodes doivent être implémentées.
Cependant , si nous pensons à une méthode dont l'implémentation est une simple exception lancée comme «non implémentée» (comme certaines méthodes de l'
Collection
interface), alors l'Collection
interface est l'exception dans ce cas, pas le cas normal. Habituellement , la classe d'implémentation devrait (et implémentera) toutes les méthodes.Le "optionnel" dans la collection signifie que la classe d'implémentation n'a pas à l'implémenter (selon la terminologie ci-dessus), et elle le lancera
NotSupportedException
).Un bon exemple -
add()
méthode pour les collections immuables - le béton implémentera simplement une méthode qui ne fait que lancerNotSupportedException
Dans le cas où
Collection
cela est fait pour éviter des arbres d'héritage désordonnés, cela rendra les programmeurs misérables - mais dans la plupart des cas, ce paradigme n'est pas conseillé et devrait être évité si possible.Mettre à jour:
À partir de java 8, une méthode par défaut a été introduite.
Cela signifie qu'une interface peut définir une méthode - y compris son implémentation.
Cela a été ajouté afin de permettre l'ajout de fonctionnalités aux interfaces, tout en prenant en charge la compatibilité descendante pour les morceaux de code qui n'ont pas besoin de la nouvelle fonctionnalité.
Notez que la méthode est toujours implémentée par toutes les classes qui la déclarent, mais en utilisant la définition de l'interface.
la source
Une interface en Java déclare simplement le contrat d'implémentation des classes. Toutes les méthodes de cette interface doivent être implémentées, mais les classes d'implémentation sont libres de les laisser non implémentées, c'est-à-dire vides. À titre d'exemple artificiel,
Maintenant, je n'ai pas été
doSomethingElse()
implémenté, le laissant libre à mes sous-classes à implémenter. C'est facultatif.Cependant, si vous parlez des interfaces de collection, comme d'autres l'ont dit, elles sont une exception. Si certaines méthodes ne sont pas implémentées et que vous les appelez, elles peuvent lever des
UnsupportedOperationException
exceptions.la source
Les méthodes facultatives de l'interface Collection signifient que l'implémentation de la méthode est autorisée à lever une exception, mais elle doit quand même être implémentée. Comme spécifié dans la documentation :
la source
new Runnable ( ) { @ Override public void run ( ) { throw new UnsupportedOperationException ( ) ; } }
:;add((T)null)
peuvent être valables dans un cas mais pas dans un autre. Autrement dit, cela parle des exceptions / comportements optionnels et des arguments ("restrictions sur les éléments" ... "élément inéligible" ... "exceptions marquées comme optionnelles") et ne traite pas des méthodes optionnelles .Toutes les méthodes doivent être implémentées pour que le code soit compilé (à part celles avec des
default
implémentations en Java 8+), mais l'implémentation n'a rien à faire fonctionnellement utile. Plus précisément, il:UnsupportedOperationException
(ou similaire)Cette dernière approche est souvent utilisée dans les classes de collection - toutes les méthodes sont toujours implémentées, mais certaines peuvent lever une exception si elles sont appelées à l'exécution.
la source
En fait, je suis inspiré par SurfaceView.Callback2. Je pense que c'est la manière officielle
Si votre classe n'a pas besoin d'implémenter des méthodes optionnelles, il suffit de "implémenter Callback". Si votre classe a besoin d'implémenter des méthodes optionnelles, "implémente simplement CallbackExtended".
Désolé pour la merde anglais.
la source
Dans Java 8 et versions ultérieures, la réponse à cette question est toujours valable mais est désormais plus nuancée.
Premièrement, ces déclarations de la réponse acceptée restent correctes:
Alors, quelle est la nuance qui est nouvelle dans Java 8? En parlant de "méthodes facultatives" une des suivantes est maintenant appropriée:
1. Une méthode dont la mise en œuvre est contractuellement facultative
La "troisième déclaration" dit que les méthodes d'interface abstraites doivent toujours être implémentées et cela reste vrai dans Java 8+. Cependant, comme dans Java Collections Framework, il est possible de décrire certaines méthodes d'interface abstraites comme "facultatives" dans le contrat.
Dans ce cas, l'auteur qui implémente l'interface peut choisir de ne pas implémenter la méthode. Le compilateur insistera sur une implémentation, cependant, et donc l'auteur utilise ce code pour toutes les méthodes facultatives qui ne sont pas nécessaires dans la classe d'implémentation particulière:
Dans Java 7 et les versions antérieures, c'était vraiment le seul type de «méthode optionnelle» qui existait, c'est-à-dire une méthode qui, si elle n'était pas implémentée, lançait une exception UnsupportedOperationException. Ce comportement est nécessairement spécifié par le contrat d'interface (par exemple, les méthodes d'interface optionnelles de Java Collections Framework).
2. Une méthode par défaut dont la réimplémentation est facultative
Java 8 a introduit le concept de méthodes par défaut . Ce sont des méthodes dont l'implémentation peut être et est fournie par la définition d'interface elle-même. Il n'est généralement possible de fournir des méthodes par défaut que lorsque le corps de la méthode peut être écrit en utilisant d'autres méthodes d'interface (c'est-à-dire les "primitives"), et quand
this
peut signifier «cet objet dont la classe a implémenté cette interface».Une méthode par défaut doit respecter le contrat de l'interface (comme toute autre implémentation de méthode d'interface doit l'être). Par conséquent, la spécification d'une implémentation de la méthode d'interface dans une classe d'implémentation est à la discrétion de l'auteur (tant que le comportement est adapté à son objectif).
Dans ce nouvel environnement, le Java Collections Framework pourrait être réécrit comme suit:
De cette façon, la méthode "facultative"
add()
a le comportement par défaut de lancer une exception UnsupportedOperationException si la classe d'implémentation ne fournit pas de nouveau comportement propre, ce qui est exactement ce que vous souhaiteriez voir se produire et qui est conforme au contrat pour List. Si un auteur écrit une classe qui ne permet pas d'ajouter de nouveaux éléments à une implémentation de List, l'implémentation deadd()
est facultative car le comportement par défaut est exactement ce qui est nécessaire.Dans ce cas, la "troisième instruction" ci-dessus est toujours vraie, car la méthode a été implémentée dans l'interface elle-même.
3. Une méthode qui renvoie un
Optional
résultatLe nouveau type final de méthode optionnelle est simplement une méthode qui renvoie un
Optional
. LaOptional
classe offre une manière nettement plus orientée objet de traiter lesnull
résultats.Dans un style de programmation courant, tel que celui couramment observé lors du codage avec la nouvelle API Java Streams, un résultat nul à tout moment provoque le blocage du programme avec une exception NullPointerException. La
Optional
classe fournit un mécanisme pour renvoyer des résultats nuls au code client d'une manière qui active le style fluide sans provoquer le blocage du code client.la source
Si nous parcourons le code de AbstractCollection.java dans grepCode qui est une classe ancêtre pour toutes les implémentations de collection, cela nous aidera à comprendre la signification des méthodes optionnelles. Voici le code de la méthode add (e) dans la classe AbstractCollection. La méthode add (e) est facultative selon l' interface de collecte
La méthode facultative signifie qu'elle est déjà implémentée dans les classes ancêtres et qu'elle lève une exception UnsupportedOperationException lors de l'appel. Si nous voulons rendre notre collection modifiable, nous devons remplacer les méthodes facultatives dans l'interface de collection.
la source
Eh bien, ce sujet a été adressé à ... ouais ... mais pensez, il manque une réponse. Je parle des "méthodes par défaut" des interfaces. Par exemple, imaginons que vous aurez une classe pour fermer n'importe quoi (comme un destructeur ou quelque chose). Disons qu'il devrait avoir 3 méthodes. Appelons-les "doFirst ()", "doLast ()" et "onClose ()".
Nous disons donc que nous voulons que tout objet de ce type réalise au moins "onClose ()", mais les autres sont facultatifs.
Vous pouvez vous en rendre compte en utilisant les "méthodes par défaut" des interfaces. Je sais, cela annulerait la plupart du temps la raison d'une interface, mais si vous concevez un cadre, cela peut être utile.
Donc, si vous voulez le réaliser de cette façon, cela ressemblerait à ceci
Que se passerait-il maintenant, si vous l'implémentiez par exemple dans une classe appelée "Test", le compilateur conviendrait parfaitement avec ce qui suit:
avec la sortie:
ou
avec la sortie:
Toutes les combinaisons sont possibles. Tout ce qui a "par défaut" peut être implémenté, mais ne doit pas, cependant tout ce qui ne doit pas être implémenté.
J'espère que ce n'est pas complètement faux que je réponds maintenant.
Passez une bonne journée à tous!
[edit1]: Veuillez noter: cela ne fonctionne que dans Java 8.
la source
Je cherchais un moyen d'implémenter l'interface de rappel, donc l'implémentation de méthodes optionnelles était nécessaire car je ne voulais pas implémenter chaque méthode pour chaque rappel.
Donc, au lieu d'utiliser une interface, j'ai utilisé une classe avec une implémentation vide telle que:
Et vous pouvez définir la variable membre CallBack comme ceci,
alors appelez-le comme ça.
De cette façon, vous n'avez pas à vous soucier de l'implémentation de toutes les méthodes par rappel, mais ne remplacez que celles dont vous avez besoin.
la source
Bien que cela ne réponde pas à la question de l'OP, il convient de noter qu'à partir de Java 8, l'ajout de méthodes par défaut aux interfaces est en fait faisable . Le
default
mot-clé placé dans la signature de méthode d'une interface donnera à une classe la possibilité de remplacer la méthode, mais ne l'exigera pas.la source
Tutoriel sur les collections Java d'Oracle:
la source