2016-07-02 1 views
0

J'ai une implémentation d'une classe Mapper qui accepte Object comme paramètre dans l'une des fonctions map(Object object). Les map(T t) repos fonctions acceptent Entier ou classe, etc.Double Dispatch lorsque la méthode accepte la classe d'objets

Lorsque je tente de passer un entier, il s'Autoboxed en entier et appelle la map(Object object) au lieu du map(Integer integer).

J'ai fait des recherches pour Double Dispatch et j'ai vu que je pouvais utiliser le Visitor Pattern. Mais cela ne s'applique pas dans mon cas car je ne passe pas d'objets personnalisés que je pourrais leur faire implémenter une interface avec accept().

La méthode susmentionnée accepte tous les objets.

Existe-t-il une sorte de solution pour le Double Dispatching avec des objets Java lorsque vous avez une méthode qui accepte également Object?

public BaseMatcher map(Object object) { 
     return something(); 
    } 

    public BaseMatcher map(Integer integer) { 
     return somethingOther(); 
    } 

    public BaseMatcher map(Class<? extends Exception> klass) { 
     return somethingOtherOther(); 
    } 

L'appel sur ces fonctions map(), serait la suivante: foo(Object object) { mapper.map(object); } qui conduit à map(Object object) invoquée.

+1

Jetez un oeil à cette question: http://stackoverflow.com/questions/1572322/overloaded-method-selection-based-on-the-parameters-real-type. Pour déterminer la signature de la méthode invoquée, il utilise le type de temps de compilation ('Object'), pas le type d'exécution. – JMSilla

+0

@JMSilla J'ai déjà recherché tous les cas possibles. C'est pourquoi j'ai demandé, parce que j'essaye de voir s'il y a une solution possible au problème. – Pavlos

Répondre

2

Tout le compilateur connaît vos objets, c'est-à-dire qu'ils sont des objets, c'est-à-dire des instances d'Object. Donc map(Object) est appelée. Si votre méthode de mappage doit faire quelque chose de différent selon le type de l'objet transmis, alors elle doit obtenir le type concret de l'objet et agir en conséquence (en utilisant instanceof, getClass(), ou whataver).

L'alternative est en effet d'utiliser le polymorphisme. Mais pour ce faire, l'appelant devra fournir une collection de Mappable, au lieu d'une collection d'objets:

private interface Mappable { 
    BaseMatcher mapMe(Mapper mapper); 
} 

public class IntegerMappable { 
    private final Integer value; 

    public IntegerMappable(Integer value) { 
     this.value = value; 
    } 

    @Override 
    public BaseMatcher mapMe(Mapper mapper) { 
     return mapper.map(this.value); 
    } 
} 

Et quand vous voulez mapper des objets, vous les envelopper dans le Mappable approprié (ou utiliser un lambda):

List<Mappable> mappables = new ArrayList<>(); 
mappables.add(new IntegerMappable(2)); 
mappables.add(new StringMappable("hello"); 
mappables.add(mapper -> mapper.map(42)); 
+0

Oui, le fait est que j'essayais d'éviter d'avoir 20-30 lignes avec des contrôles pour exampleOf. Existe-t-il un exemple avec la collection Mappable que vous avez mentionnée en dernier? – Pavlos