测试隐式转换是否可用

9

我正在尝试检测是否存在隐式转换,根据其执行一些代码。例如:

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

例如,x是一个Int类型的变量,应该转换为RichInt类型。在Scala中是否可能实现?如果可以,该如何实现?
谢谢。

4
隐式转换只存在于编译时而不是运行时。如果你想测试这种转换是否存在,你可以写下代码并尝试编译它。编译器会告诉你是否可以编译。 - kiritsuku
2个回答

12

正如其他人已经提到,隐式是在编译时解析的,因此您可能应该使用类型类来解决此类问题。这样您就有了一个优势,可以将功能扩展到其他类型。

此外,您可以要求现有的隐式值,但除了默认参数外,没有直接表达不存在隐式值的方法。

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

谢谢您的回答。例如,当使用“canConvert[Boolean,Ordered[Boolean]]”进行测试时,它返回false。我以为会使用转换为RichBoolean,但似乎不是这样。出了什么问题? - Alban Linard
没有代码,我只能猜测:你可能像这样用括号调用它:canConvert[Boolean,Ordered[Boolean]]()。然后编译器会填充默认参数 - 这不是你想要的。要么从调用中删除括号,要么在隐式参数之前添加一个空参数列表。 - Moritz
@saucisson 我更新了代码,包括一个空参数列表 - 现在无论您是否使用空参数列表调用canConvert方法都没有关系。 - Moritz

9
您可以尝试将其传递给需要对应默认值为null的隐式参数的方法:
def toB[A](a: A)(implicit convertFct: A => B = null) =
  if (convertFct != null)
    convertFct(a)
  else
    someOtherThing(a)

请注意,对我来说,在运行时检查这一点似乎很奇怪,因为编译器在编译时就知道是否有这样的转换函数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接