web-dev-qa-db-fra.com

Java 8 ajoute l'extension / la méthode par défaut à la classe

Je recherche un Java équivalent à la fonctionnalité des méthodes d'extension C #. Maintenant, j'ai lu à propos de Java 8 méthodes par défaut, mais pour autant que je puisse voir) , Je ne peux que les ajouter aux interfaces ...

... y a-t-il une fonctionnalité de langage qui me permettra d'écrire une méthode d'extension pour une classe finale qui n'implémente pas d'interface? (Je préfère ne pas avoir à l'envelopper ...)

34
Cheetah

Les méthodes d'extension C # ne sont que du sucre syntaxique pour les méthodes statiques qui prennent le type étendu comme premier argument. Java les méthodes par défaut sont quelque chose de complètement différent. Pour imiter les méthodes d'extension C #, écrivez simplement les méthodes statiques habituelles. Cependant, vous n'aurez pas le sucre syntaxique; Java ne pas cette fonctionnalité.

Les méthodes Java par défaut sont de vraies méthodes virtuelles. Par exemple, ils peuvent être remplacés. Considérons une classe X héritant d'une interface I qui déclare une méthode foo() par défaut. Si X ou l'une de ses super classes ne déclare pas de méthode foo() propre, alors X obtiendra l'implémentation foo() de I . Maintenant, une sous-classe Y de X peut remplacer X.foo() comme une méthode habituelle. Ainsi, les méthodes par défaut ne sont pas seulement du sucre syntaxique. Ce sont de véritables extensions du mécanisme de substitution et d'héritage de la méthode qui ne peuvent pas être imitées par d'autres fonctionnalités du langage.

Les méthodes par défaut nécessitent même une prise en charge spéciale de VM, donc elles ne sont même pas uniquement une fonction de compilation: pendant le chargement de la classe, la hiérarchie d'une classe doit être vérifiée pour déterminer les méthodes par défaut dont elle héritera. , cette décision est prise au moment de l'exécution, pas au moment de la compilation. Ce qui est intéressant, c'est que vous n'avez pas à recompiler une classe lorsqu'une interface dont elle hérite obtient une nouvelle méthode par défaut: Le VM , au moment du chargement de la classe, lui attribuera cette nouvelle méthode.

23
gexicide

Java n'a pas de méthodes d'extension. Les méthodes par défaut ne sont pas des méthodes d'extension. Regardons chaque fonctionnalité.

Les méthodes par défaut de Java

Problèmes résolus:

  1. De nombreux objets peuvent implémenter la même interface et tous peuvent utiliser la même implémentation pour une méthode. Une classe de base pourrait résoudre ce problème, mais uniquement si les implémenteurs d'interface n'ont pas déjà une classe de base comme Java ne prend pas en charge l'héritage multiple.
  2. Une API souhaite ajouter une méthode à une interface sans casser les consommateurs d'API. L'ajout d'une méthode avec une implémentation par défaut résout ce problème.

Les méthodes par défaut de Java sont une fonctionnalité permettant d'ajouter une implémentation par défaut à une interface. Ainsi, les objets qui étendent une interface n'ont pas à implémenter la méthode, ils peuvent simplement utiliser la méthode par défaut.

interface IA { default public int AddOne(int i) { return i + 1; } }

Tout objet qui implémente IA n'a pas à implémenter AddOne car il existe une méthode par défaut qui serait utilisée.

public class MyClass implements IA { /* No AddOne implementation needed */ } 

C # n'a pas cette fonctionnalité et serait grandement amélioré en ajoutant cette fonctionnalité. (Mise à jour: fonctionnalité à venir en C # 8)

Méthode d'extension de C #

Problèmes résolus:

  1. Possibilité d'ajouter des méthodes aux classes scellées.
  2. Possibilité d'ajouter des méthodes aux classes de bibliothèques tierces sans forcer l'héritage.
  3. Possibilité d'ajouter des méthodes aux classes de modèles dans des environnements où les méthodes des classes de modèles ne sont pas autorisées pour des raisons de convention.
  4. La capacité pour intellisense de vous présenter ces méthodes.

Exemple: la chaîne de type est une classe scellée en C #. Vous ne pouvez pas hériter de la chaîne car elle est scellée. Mais vous pouvez ajouter des méthodes que vous pouvez appeler à partir d'une chaîne.

var a = "mystring";
a.MyExtensionMethed()

Java n'a pas cette fonctionnalité et serait grandement améliorée en ajoutant cette fonctionnalité.

Conclusion

Il n'y a rien de similaire sur les méthodes par défaut de Java et les fonctionnalités des méthodes d'extension de C #. Ils sont complètement différents et résolvent des problèmes complètement différents.

23
Rhyous

Les méthodes d'extension C # sont statique et se-site, tandis que les méthodes par défaut de Java sont virtual et declaration-site.

Ce que je pense que vous espérez, c'est la possibilité de "patch de singe" une méthode dans une classe que vous ne contrôlez pas, mais Java ne vous donne pas cela (par conception; il a été considéré et rejeté.)

Un autre avantage des méthodes par défaut par rapport à l'approche C # est qu'elles sont détectables par réflexion et qu'en fait de l'extérieur, elles ne sont pas différentes des méthodes d'interface "normales".

Un avantage des méthodes d'extension de C # par rapport aux méthodes par défaut de Java est qu'avec les génériques réifiés de C #, les méthodes d'extension sont injectées dans types, pas classes, vous pouvez donc injecter une fonction sum() méthode dans List<int>.

Surtout, la principale différence philosophique entre les méthodes par défaut de Java et les méthodes d'extension de C # est que C # vous permet d'injecter des méthodes dans des types vous ne contrôlez pas (ce qui est sûrement pratique pour les développeurs), tandis que les méthodes d'extension de Java sont un partie de première classe de l'API dans laquelle ils apparaissent (ils sont déclarés dans l'interface, ils sont détectables par réflexion, etc.) Cela reflète plusieurs principes de conception; les développeurs de bibliothèques devraient pouvoir garder le contrôle de leurs API et l'utilisation des bibliothèques devrait être transparente - la méthode d'appel x() sur le type Y devrait signifier la même chose partout.

21
Brian Goetz

Il est possible d'avoir des méthodes d'extension avec quelques astuces.

Vous pouvez essayer Lombok ou XTend. Bien que les méthodes d'extension ne soient pas fournies avec l'implémentation prête à l'emploi Java implémentation, Lombok et XTend offrent une solution entièrement fonctionnelle.

Lombok est un cadre de traitement de code autonome simple, ce qui rend la plupart des problèmes critiques Java spécifiques moins douloureux, y compris les méthodes d'extension: https://projectlombok.org/features/experimental/ ExtensionMethod.html

Xtend http://www.Eclipse.org/xtend/ avance de quelques années et implémente un langage qui est une combinaison des meilleures parties des langages modernes tels que Scala en plus de Java et Java système de type. Cela permet d'implémenter certaines classes dans Xtend et d'autres dans Java dans le même projet. Le code Xtend est conforme au Java Java, donc aucune magie JVM ne se produit sous le capot. En revanche, c'est un peu trop si vous n'avez que des méthodes d'extension manquantes .

JPropel https://github.com/nicholas22/jpropel-light implémente les méthodes d'extension de style LINQ dans Java utilisant Lombok. Cela peut valoir le coup d'œil :)

7
Gee Bee