FAQ

Comment créer une multi-méthode ?

Il existe deux méthodes statiques dans la classe MultiMethod :

  MultiMethod create(Class clazz,String name,int argLength)
  MultiMethod create(Class clazz,String name,int argLength,boolean onlyPublic)
 
avec
clazz
correspond à la classe dans laquelle on va aller rechercher les méthodes.
name
correspond au nom des méthodes, les différentes méthodes sont des surdéfinitions.
argLength
nombre d'argument des différentes méthodes.
onlyPublic
indique que l'on doit chercher seulement dans les méthodes publiques (false par défaut)

Quel est la visibilité d'une multi-méthode si les méthodes dont elle dépend n'ont pas la même visibilité ?

La visibilité d'une multi-méthode correspond à la visibilité de la méthode la plus visible.
Avec PUBLIC > PROTECTED > PACKAGE > PRIVATE
donc avec les méthodes :

  public void print(double d) {...}
  private void print(int i) {...}
 

La multi-méthode correspondante aura une visibilité PUBLIC.

Quel est la difference entre un objet MultiMethod et une objet METHOD sur une une seule methode ?

class Test {
  static class A {
    public void m() {
      System.out.println("A");
    } 
  }

  static class B extends A {
    public void m() {
      System.out.println("B");
    }
  }

  public static void main(String[] args) 
    throws Exception
  {
    Method m=B.class.getMethod("m",null);
    m.invoke(new A(),null);
    // throws IllegalArgumentException, object isn't an instance
    // of the declaring class

    MultiMethod mm=MultiMethod.create(B.class,"m",0,true);
    mm.invoke(new A(),null);
    // print "A"
  }
}
 

Contrairement au mécanisme des Methodes, l'implementation des multi-méthodes considère que les méthodes A.m() et B.m() sont en faite, une seul et meme méthode donc il est possible d'appeler la multi-méthode "m" de la classe B avec un objet de la class A.

Peut-on appeler une multi-méthode PUBLIC même si la meilleur méthode est PRIVATE ?

Oui, c'est le un cas ou le mécanisme des multi-méthodes passe outre le mécanisme de visibilité de Java.
Le mécanisme des multi-méthodes regarde uniquement la visibilité de la multi-méthode et non, la visibilité de chaque méthode sous-jacente.

class Algo {
  private void print(int i) {
    System.out.println("int "+i);
  }
  public void print(double d) {
    System.out.println("double "+d);
  }
}

class Test {
  public static void main(String[] args) 
    throws Exception
  {
    MultiMethod mm=MultiMethod.create(Algo.class,"print",1);
    mm.invoke(new Algo(),new Object[]{new Integer(3)},
      new Class[]{Integer.TYPE});
  }
}
 

Pourquoi la méthode invoke() ne marche pas sur les types primitifs ?

Il n'y a pas de convertion explicite pour transformer un Integer en int lors de la recherche de la meilleur méthode (uniquement lors de la recherche, il n'y pas de problème lors de l'appel)
Si l'on veut utiliser la convertion, il faut le faire explicitement en indiquant à la méthode invoke(Object, Object[], Class[]) quel est le type réel de l'objet, par exemple en utilisant Integer.TYPE
Cette méthode permet aussi d'appeler la meilleur méthode non-plus en fonction du type réel des paramètres mais en fonction du type des classes passées en paramètre.
Ceci pourrait être rajouter dans les futures version du framework.

class Test {
  void print(int i) {
    System.out.println("int "+i);
  }

  public static void main(String[] args) 
    throws Exception
  {
    MultiMethod mm=MultiMethod.create(Test.class,"print",1);
    
    // mm.invoke(new Test(),new Object[]{new Integer(3)});
    // this method look for the method print(Integer)

    mm.invoke(new Test(),new Object[]{new Integer(3)},
      new Class[]{Integer.TYPE});
  }
}
 

Pourquoi un appel à invoke() lève l'exception MultipleMatchingMethodsException ?

Cette exception est levé lorsque le mécanisme d'appel des multi-méthodes détecte que plusieurs méthodes peuvent être appelé suivant les arguments passés à la méthode invoke et que le mécanisme ne sait pas choisir la meilleur méthode.
La résolution des conflits suis les mêmes règles que la résolution statique des méthodes effectuée par le compilateur. (cf JLS).

class Test {
  class A implements Serializable, Cloneable {
    // ...
  }

  private static void m(Serializable s) {
    System.out.println("serializable");
  }
  
  private static void m(Cloneable c) {
    System.out.println("cloneable");
  }

  public static void main(String[] args) 
    throws Exception
  {
    MultiMethod mm=MultiMethod.create(Test.class,"m",1);
    mm.invoke(null,new Object[]{new A()});
    // throws MultipleMatchingMethodsException
  }
}