web-dev-qa-db-fra.com

Java équivalent aux méthodes d'extension C #

Je cherche à implémenter une fonctionnalité dans une liste d'objets comme je le ferais en C # en utilisant une méthode d'extension.

Quelque chose comme ça:

List<DataObject> list;
// ... List initialization.
list.getData(id);

Comment je fais ça en Java?

161
Fabio Milheiro

Java ne supporte pas les méthodes d'extension.

Au lieu de cela, vous pouvez créer une méthode statique régulière ou écrire votre propre classe.

177
SLaks

Les méthodes d'extension ne sont pas simplement des méthodes statiques et pas simplement du sucre de syntaxe de commodité, elles sont en fait un outil assez puissant. Le principal est la possibilité de remplacer différentes méthodes en fonction de l’instanciation de différents paramètres génériques. Ceci est similaire aux classes de types de Haskell, et en fait, il semble qu’elles soient en C # pour prendre en charge les monades de C # (c’est-à-dire LINQ). Même en supprimant la syntaxe LINQ, je ne sais toujours pas comment implémenter des interfaces similaires en Java.

Et je ne pense pas qu’il soit possible de les implémenter en Java, à cause de la sémantique d’effacement de type des paramètres génériques par Java.

51
user1686250

Projet Lombok fournit une annotation @ExtensionMethod qui peut être utilisé pour obtenir la fonctionnalité que vous demandez.

16
Thomas Eizinger

Le langage XTend - qui est un super-ensemble de Java, et compile pour Java1- soutient cela.

7
Sam Keays

Une autre option consiste à utiliser ForwardingXXX classes de la bibliothèque google-guava.

6
Aravind R. Yarram

Java n'a pas cette fonctionnalité. À la place, vous pouvez créer une sous-classe régulière de votre implémentation de liste ou créer une classe interne anonyme:

List<String> list = new ArrayList<String>() {
   public String getData() {
       return ""; // add your implementation here. 
   }
};

Le problème est d'appeler cette méthode. Vous pouvez le faire "en place":

new ArrayList<String>() {
   public String getData() {
       return ""; // add your implementation here. 
   }
}.getData();
6
AlexR

Techniquement, C # Extension n’a pas d’équivalent en Java. Mais si vous voulez implémenter de telles fonctions pour un code plus propre et une facilité de maintenance, vous devez utiliser le framework Manifold.

package extensions.Java.lang.String;

import manifold.ext.api.*;

@Extension
public class MyStringExtension {

  public static void print(@This String thiz) {
    System.out.println(thiz);
  }

  @Extension
  public static String lineSeparator() {
    return System.lineSeparator();
  }
}
6
M.Laida

Manifold fournit Java avec le style C # méthodes d'extension et plusieurs autres fonctionnalités. Contrairement à d'autres outils, Manifold n'a aucune limitation et ne - souffre de problèmes avec les génériques, les lambdas, IDE etc.). Manifold fournit plusieurs autres fonctionnalités telles que le style F # types personnalisés , le style TypeScript - interfaces structurelles , et Javascript-style types expand .

De plus, IntelliJ fournit un support complet pour Manifold via Manifold plugin .

Manifold est un projet open source disponible sur github .

5
Scott

Il semble y avoir un petit risque que Defender Methods (méthodes par défaut) le fasse Java). Cependant, pour autant que je sache, ils ne permettent que author d'un interface pour l'étendre rétroactivement, pas pour des utilisateurs arbitraires.

Defender Methods + Interface Injection serait alors en mesure d’implémenter complètement les méthodes d’extension de style C #, mais AFAICS, Interface Injection n’est même pas encore sur la feuille de route Java 8.

4
Jörg W Mittag

Un peu tard pour le parti sur cette question, mais au cas où quelqu'un le jugerait utile, je viens de créer une sous-classe:

public class ArrayList2<T> extends ArrayList<T> 
{
    private static final long serialVersionUID = 1L;

    public T getLast()
    {
        if (this.isEmpty())
        {
            return null;
        }
        else
        {       
            return this.get(this.size() - 1);
        }
    }
}
3
magritte

On pourrait utiliser le motif de conception orienté objet décorateur . Un exemple de ce modèle utilisé dans la bibliothèque standard de Java serait le DataOutputStream .

Voici un code pour augmenter les fonctionnalités d'une liste:

public class ListDecorator<E> implements List<E>
{
    public final List<E> wrapee;

    public ListDecorator(List<E> wrapee)
    {
        this.wrapee = wrapee;
    }

    // implementation of all the list's methods here...

    public <R> ListDecorator<R> map(Transform<E,R> transformer)
    {
        ArrayList<R> result = new ArrayList<R>(size());
        for (E element : this)
        {
            R transformed = transformer.transform(element);
            result.add(transformed);
        }
        return new ListDecorator<R>(result);
    }
}

P.S. Je suis un grand fan de Kotlin . Il a des méthodes d’extension et s’exécute également sur la machine virtuelle Java .

1
Eric