2009-05-28 8 views
4

Fondamentalement, ce que je veux, ce sont deux méthodes publiques avec des valeurs de retour légèrement différentes pour appeler la même méthode pour faire le travail nécessaire. Ils retournent tous deux la valeur de retour de la méthode privée, mais la méthode privée saura comment retourner la valeur correcte en fonction de la méthode publique qui l'a appelée.Modification d'un type de retour en fonction de la méthode d'appel

méthodes Exemple:

public Map<Type1, Type3> doSomething1(); 
public Map<Type2, Type3> doSomething2(); 

private Map<Type1/Type2, Type3> doSomething(); 

Ainsi, dans l'exemple ci-dessus, doSomething() retourne soit Type1 ou Type2 comme type clé de la carte, selon la méthode publique appelée. Il serait capable d'effectuer une vérification simple et de remplir la carte avec des objets du type correct.

Peut-être que cela peut être fait grâce à une réflexion Java intelligente? Je ne suis pas sûr. Tout cela semble assez douteux, donc s'il y a une bien meilleure façon de faire, je suis tout ouïe.

Répondre

8

Je suggère fortement que réflexion-mojo devrait être évitée ici. Une fonction doit faire une chose proprement et ne doit pas dépendre de qui l'appelle.

Une meilleure façon de faire la même chose serait de refactoriser doSomething() en fonctions plus petites, créer deux nouvelles fonctions appelées doSomethingFor1() et doSomethingFor2(). Ces deux fonctions peuvent réutiliser les parties refactorisées de l'ancien doSomething().

Appelez maintenant DoSomething1() et utilisez doSomethingFor1().

De même, doSomething2() doit utiliser doSomethingFor2().

acclamations,

jrh.

+0

Oui, c'est aussi ce que j'ai imaginé. Je suis d'accord qu'une méthode ne devrait pas avoir de dépendance sur son appelant. Mais que faire si doSomethingFor1() et doSomethingFor2() partagent exactement le même code, la seule chose qui les différencie étant l'objet qu'ils ajoutent comme la clé de la carte? Ce ne serait pas une grosse duplication de code? –

+2

La duplication doit être contrée en refacturant correctement les fonctions et en plaçant le code dupliqué dans les fonctions/méthodes communes. – jrharshath

+0

@Le Dissonant: utilisez donc un paramètre pour indiquer quelle touche ajouter.Ne le déduisez pas de qui vous a appelé. –

1

Si tout le reste échoue, laissez la méthode privée retourner Object et utiliser cast dans les méthodes publiques.

0

Vous pouvez certainement le faire en analysant la pile en utilisant la réflexion. Mais je voudrais essayer de l'éviter et:

  • retour type de base (ou objet) et de le jeter correctement dans l'appelant, que vous devrez faire de toute façon
  • passer un paramètre à la méthode privée indiquant en quelque sorte ce que faire et retourner
1

La première question est pourquoi vous avez besoin de cette structure exacte.

Mais la façon dont la sécurité est de faire revenir

public Map<Object, Type3> doSomething(); 

s'il n'y a pas supertype commun pour Type1 et Type2. Si vous avez un super type commun, vous pouvez l'utiliser à la place de l'objet.

Il serait préférable de refactoriser le code que cela n'est pas nécessaire.

+0

Je me demandais, comment wouldSomething() savoir quelle sous-classe de l'objet (par exemple Type1 ou Type2) à ajouter en tant que clé de la carte? Il doit être en mesure d'effectuer une vérification. –

1

J'ai besoin d'un peu d'information qui manque à votre question, comme par exemple comment type1 et type 2 sont instanciés, car vous ne pouvez pas instancier directement à partir de paramètres de type arbitraires. Maintenant, nous supposons qu'il existe des données communes utilisées pour instancier à la fois type1 et type2. Sinon, il n'y a pas de bonne raison d'utiliser une méthode pour les deux. Dans ce dernier cas, cela signifierait qu'une fonction fait deux choses distinctes en fonction du type, ce qui est une mauvaise programmation.Si vous allez avoir une logique qui est directement basée sur la méthode d'appel, il suffit d'avoir deux méthodes privées et de refactoriser les choses communes.

Si vous ne l'instanciation différemment, en fonction de certaines données, la meilleure façon de le faire serait de déclarer une interface privée intérieure:

private interface Instantiator<T> { 

    T getNew(Data data);   

} 

Maintenant, en supposant que vous pouvez instancier vos types, vous peut effectivement utiliser ceci:

private <T> Map<T,Type3> doSomething(Instantiator<T> instantiator) {...} 

comme méthode de signature, et que les méthodes publiques l'appellent avec l'implémentation Instantiator appropriée.

3

Veuillez noter:J'ai mal compris la question, donc cette réponse est à l'opposé de ce que la question demande. Je vais laisser cela en référence en tant que wiki communautaire, mais cela ne répond pas à la question initiale.

S'il y avait un sous-type commun à Type1 et Type2 appelé SuperType, puis en disant que le premier type est ? extends SuperType fonctionnerait.

Voici un petit exemple qui utilise Integer et Double comme les deux types, et leur ancêtre commun comme Number:

private Map<Integer, String> doSomethingForInteger() { 
    HashMap<Integer, String> map = new HashMap<Integer, String>(); 
    map.put(10, "Hello"); 
    return map; 
} 

private Map<Double, String> doSomethingForDouble() { 
    HashMap<Double, String> map = new HashMap<Double, String>(); 
    map.put(3.14, "Apple"); 
    return map; 
} 

public Map<? extends Number, String> doSomething(boolean b) { 
    if (b) 
    return doSomethingForInteger(); 
    else 
    return doSomethingForDouble(); 
} 

Ici, la méthode doSomething renverra deux types de HashMap s en fonction du boolean qui est transmis. HashMap<Integer, String> ou HashMap<Double, String> est renvoyé par la méthode doSomething.

En fait appeler doSomething avec un boolean peut être accompli comme ceci:

Map<? extends Number, String> map1 = doSomething(true); 
Map<? extends Number, String> map2 = doSomething(false); 

map1 se terminera avec Hashmap<Integer, String>, tandis que map2 va se Hashmap<Double, String>.

+0

J'apprécie la réponse, mais vous l'avez dans le mauvais sens. Je ne veux pas que la méthode supertype soit publique, et je veux que toutes les tâches d'instantanéisation/de manipulation de la carte soient effectuées uniquement dans une seule méthode privée (c'est-à-dire sans duplication). –

+0

Oups, désolé, je l'ai mélangé ... – coobird

0

Vous pouvez modéliser l'idée d'une fermeture:

interface MappingClosure { 
    public void map(Map, MapProvider); 
} 


class Caller implements MappingClosure { 
    public void map(final Map MAP, final MapProvider CALLEE) { 
     this.MAP = specialise(MAP); 
     // CALLEE USED AS KEY 
    } 
} 


class MapProvider { 
    public Map getMap(final MappingClosure CALLER) { 
     return CALLER.map(mapInstance, this); 
    } 
} 

modifier ensuite les données pour répondre aux objets besoins sont reporté à une méthode avec l'ob ject qui le nécessite.

Questions connexes