2
votes

Paramètres génériques facultatifs ou par défaut

Disons que j'ai 3 paramètres génériques:

  public static interface Mapper<V,T = any,E = any> {
    public void map(KeyValue<V> v, AsyncCallback<T,E> cb);
  }

Comment puis-je rendre les paramètres facultatifs? Comment puis-je donner aux paramètres des valeurs par défaut si l'utilisateur ne fournit que le premier paramètre?

En utilisant TypeScript, cela ressemblerait à:

  public static interface Mapper<V,T,E> {
    public void map(KeyValue<V> v, AsyncCallback<T,E> cb);
  }

donc si le l'utilisateur ne fournit pas T et E, ils sont par défaut any . Existe-t-il un moyen de faire cela avec Java?


4 commentaires

C'est impossible en Java.


Ouais, c'est bizarre, car cela vous permet de fournir 0, 3, mais pas 1 ou 2.


0 est que les paramètres sont appelés "type brut", ils utilisent en fait une classe générique comme non générique. C'est une chose assez compliquée, pas seulement d'omettre des paramètres.


Il existe toujours des types bruts ( Mapper ). La possibilité de spécifier arbitrairement des arguments de type de sélection est absurde, à mon avis (et je pense que l'approche de Java consistant à ne pas inclure de telles choses dans le langage est raisonnable)


4 Réponses :


1
votes

Je dirais non. Java apprécie quand toutes ses variables sont définies comme un certain type et ne changent jamais. Si vous voulez trouver le plus de flexibilité, essayez de trouver la plus grande superclasse possible, comme dans peut-être T = Object et E = Object. Plus tard, lorsque vous aurez besoin d'utiliser l'objet, vous pouvez le convertir en ce que vous voulez? Peut-être?


0 commentaires

2
votes

Si vous pensez à quelque chose du genre:

  • Avoir une méthode qui prend 3 paramètres (génériques)
  • Mais parfois, vous voudrez qu'il ait 2 paramètres

Ensuite, voici la manière d'aborder cela. Dans le cas contraire, rendre les paramètres facultatifs n'est pas autorisé à mon avis.

interface InterfaceA<T, T> {
      boolean myMEthod(T clazz, UserRef user, String type, T clazz2) {
             return false;
      }
}  

interface InterfaceB<T> extends InterfaceA<T, T> {
      default boolean myMEthod(T clazz, UserRef user, String type) {
             return myMEthod(clazz, user, type, clazz);
      }
}   

Cela vous permet d'implémenter InterfaceB partout où vous voulez sauter un paramètre. Vous pouvez transmettre le même paramètre (du même type) deux fois, passer null ou une valeur par défaut.
J'espère que cela fonctionne pour votre cas.


0 commentaires

1
votes

Je vois deux façons de le faire (ou au moins de contourner le problème):

  1. La première façon est d'implémenter une méthode avec tous vos paramètres et de passer null à la place du paramètre si vous n'en avez pas besoin. Puis manipulez-le dans le corps de votre méthode. Cela devrait ressembler à ceci:

    public void myMethod(Sometype param1, Sometype param2, Sometype param3) {
        //Test if your paramaters are null or not then do what you want
    }
    

    Et vous pouvez appeler votre méthode comme ceci (si vous n'avez pas besoin du deuxième paramètre par exemple): myInstance.myMethod (param1, null, param2);

    Vous pouvez le faire comme ceci, mais je ne recommande PAS d'utiliser cette astuce, car elle contre-intuitif pour l'utilisateur, et votre méthode sera verbeuse et "impure" ...

  2. Il existe une deuxième façon de procéder. même si c'est beaucoup plus verbeux que TypeScript ou Kotlin, vous pouvez simplement définir plusieurs méthodes avec les paramètres requis. Par exemple une méthode avec seulement le deuxième paramètre, une avec le premier et le troisième paramètre, etc ... C'est juste une surcharge de méthode de base , mais cela fonctionne parfaitement! Je pense que c'est l'un des moyens les plus "conviviaux pour Java" de le faire.

J'espère que je vous ai aidé


0 commentaires

1
votes

Comme beaucoup de langages, il n'y a pas de saisie facultative ou progressive en Java. Les règles de saisie sont probablement assez compliquées en l'état. Il n'y a pas non plus d'arguments de type par défaut, mais cela ne semble pas être le problème majeur ici.

Dans votre cas, il semble que rendre la saisie plus conviviale pour le client résout le problème sans avoir à aller plus loin. Je suppose que le E dans AsyncCallback est pour "exception" et T est, comme dans AsyncCallback de GWT, pour un paramètre de méthode.

public class MapperAny<V> implements Mapper<V,Object,Throwable> {
    private final Mapper<V,Object,Throwable> target;
    // A static creation method would be nicer, but ctor conventional.
    public MapperAny(Mapper<V,Object,Throwable> target) {
        this.target = target;
    }
    public void map(KeyValue<V> v, AsyncCallback<T,E> cb) {
        target.map(v, cp);
    }
    // unwrap
    public Mapper<V,Object,Throwable> mapper() {
        return target;
    }
}

Cela permet à tout Mapper particulier de prendre n'importe quel AsyncCallback applicable.

Nous pouvons être plus explicites sur l'exception - utile si nous devons définir un jette n'importe où.

public static interface Mapper<V,T,E extends Throwable> {

Si une référence à un Le mappeur pourrait prendre n'importe quel AsyncCallback , le déclarer de type Mapper pour certains V . P >

Si vous vouliez désespérément une forme courte de Mapper avec une déclaration concise pour vous pourriez introduire un adaptateur.

public static interface Mapper<V,T,E> {
    public void map(KeyValue<V> v, AsyncCallback<? super T,? extends E> cb);
}

Si vous vouliez le même chose pour AsyncCallback , c'est un peu plus difficile. Il n'y a pas d'opposé dénotable de Object (c'est-à-dire le type de null).


0 commentaires