2011-04-19 7 views
9

J'essaie de détecter si une conversion implicite existe et, selon le cas, d'exécuter du code. Par exemple:Test si la conversion implicite est disponible

if (x can-be-converted-to SomeType) 
    return something(conversion(x)) 
else 
    return someotherthing(x) 

Par exemple, x est un Int et doit être converti en un RichInt. Est-ce possible en Scala? Si oui, comment?

Merci

+4

Les conversions implicites n'existent qu'au moment de la compilation et non au moment de l'exécution. Si vous voulez tester si une telle conversion existe, vous pouvez écrire le code et essayer de le compiler. Le compilateur vous dira s'il peut être compilé. – sschaef

Répondre

11

Comme d'autres implicits déjà mentionnés sont résolus au moment de la compilation, vous devriez peut-être plutôt utiliser des classes de types pour résoudre des problèmes comme celui-ci. De cette façon, vous avez l'avantage de pouvoir étendre les fonctionnalités à d'autres types plus tard.

Vous pouvez également simplement demander une valeur implicite existante, mais vous n'avez aucun moyen d'exprimer directement la non-existence d'une valeur implicite, à l'exception des arguments par défaut.

La solution de Jean-Phiippe utilisant un argument par défaut est déjà assez bonne mais le null pourrait être éliminé si vous définissiez un singleton qui peut être mis à la place du paramètre implicite. Rendez-le privé car il n'est en fait d'aucune utilité dans un autre code et peut même être dangereux car des conversions implicites peuvent se produire implicitement.

private case object NoConversion extends (Any => Nothing) { 
    def apply(x: Any) = sys.error("No conversion") 
} 

// Just for convenience so NoConversion does not escape the scope. 
private def noConversion: Any => Nothing = NoConversion 

// and now some convenience methods that can be safely exposed: 

def canConvert[A,B]()(implicit f: A => B = noConversion) = 
    (f ne NoConversion) 

def tryConvert[A,B](a: A)(implicit f: A => B = noConversion): Either[A,B] = 
    if (f eq NoConversion) Left(a) else Right(f(a)) 

def optConvert[A,B](a: A)(implicit f: A => B = noConversion): Option[B] = 
    if (f ne NoConversion) Some(f(a)) else None 
+0

Merci pour cette réponse. Lorsqu'il est testé par exemple avec "canConvert [Boolean, Ordered [Boolean]]", il renvoie false. Je pensais que la conversion à RichBoolean serait utilisée, il ne semble pas. Qu'est-ce qui ne va pas? –

+0

Sans le code que je devrais deviner: probablement vous l'avez appelé avec des parenthèses comme ceci: 'canConvert [Boolean, Ordered [Boolean]]()'. Le compilateur remplit alors le paramètre par défaut - ce qui n'est pas ce que vous voulez. Supprimez la parenthèse de l'appel ou ajoutez une liste de paramètres vide avant les paramètres implicites. – Moritz

+0

@saucisson J'ai mis à jour le code pour inclure une liste de paramètres vide - maintenant, cela n'a pas d'importance si vous appelez la méthode 'canConvert' avec ou sans liste de paramètres vide. – Moritz

9

Vous pouvez essayer de passer à une méthode qui a besoin du paramètre implicite correspondant à un défaut de null:

def toB[A](a: A)(implicit convertFct: A => B = null) = 
    if (convertFct != null) 
    convertFct(a) 
    else 
    someOtherThing(a) 

Notez qu'il semble curieux de me vérifier lors de l'exécution, parce que le compilateur sait au moment de la compilation si une telle fonction de conversion est disponible.