2011-04-19 31 views
9

我试图检测隐式转换是否存在,并根据它执行一些代码。例如:测试隐式转换是否可用

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

例如,x是一个Int,应该转换为RichInt。 这可能在斯卡拉?如果是,如何?

感谢

+4

隐式转换仅在编译时和不存在的在运行时。如果你想测试这种转换是否存在,你可以写下代码并尝试编译它。编译器会告诉你它是否可以编译。 – sschaef 2011-04-19 14:30:37

回答

11

正如其他人已经提到implicits在编译时间,所以也许你应该宁愿用类型类来解决这样的问题解决了。这样你就可以将功能扩展到其他类型。

您也可以只需要现有的隐含价值,但没有直接表达的隐含价值不存在除了默认参数的方式。

Jean-Phiippe使用默认参数的解决方案已经相当不错了,但如果您定义了一个可替代隐式参数的单例,则可以取消null。将它设为私有是因为它在其他代码中实际上没有用处,甚至可能是危险的,因为隐式转换可能会隐式发生。

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

感谢您的回答。当使用“canConvert [布尔,有序[布尔]]”进行测试时,它返回false。我认为将会使用转换为RichBoolean,但似乎没有。哪里不对? – 2011-04-21 07:44:04

+0

如果没有代码,我将不得不猜测:可能你用括号调用它:'canConvert [Boolean,Ordered [Boolean]]()'。编译器然后填入默认参数 - 这不是你想要的。从调用中删除括号或在隐式参数之前添加一个空参数列表。 – Moritz 2011-04-21 11:38:45

+0

@saucisson我更新了代码以包含一个空的参数列表 - 现在如果您调用具有或不具有空参数列表的'canConvert'方法并不重要。 – Moritz 2011-04-21 12:02:13

9

你可以尝试将它传递给需要相应的隐含参数与null默认的方法:

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

注意,它看起来好奇,我在运行时检查这一点,因为编译器在编译时知道这样的转换函数是否可用。