隐式值的隐式转换是否可以满足隐式参数?

Rob*_*ley 1 scala implicit-conversion implicit-parameters

我正在定义一些Scala implicits,以便更轻松地使用特定的不可更改的Java类集.下面的Scala代码是一个简单的例子,显然看起来很疯狂,在现实世界中,我试图从Monkey,Tree&Duck中隐含地获取特定资源(而不是数字时代),以便在各种方法中使用purchaseCandles():

// actually 3 Java classes I can not change:
case class Monkey(bananas: Int) 
case class Tree(rings: Int)
case class Duck(quacks: Seq[String])

// implicits I created to make my life easier...
implicit def monkey2Age(monkey: Monkey): Int = monkey.bananas / 1000
implicit def tree2Age(tree: Tree): Int = tree.rings
implicit def duck2Age(duck: Duck): Int = duck.quacks.size / 100000

// one of several helper methods that I would like to define only once,
// only useful if they can use an implicit parameter.
def purchaseCandles()(implicit age: Int) = {
  println(s"I'm going to buy $age candles!")
}

// examples of usage
{
  implicit val guest = Monkey(10000)

  purchaseCandles()
}

{
  implicit val guest = Tree(50)

  purchaseCandles()
}

{
  implicit val guest = Duck(Seq("quack", "quack", "quack"))

  purchaseCandles()
}
Run Code Online (Sandbox Code Playgroud)

编译器错误,发生3次:

could not find implicit value for parameter age: Int 
purchaseCandles()
               ^
Run Code Online (Sandbox Code Playgroud)

抛开这个示例代码疯狂的许多不同方式,我真正的问题是:隐式值的隐式转换是否满足Scala中的隐式参数?

Imp*_*ive 5

简答:不.Scala的编译器只会寻求应用单个隐式,所以如果它没有发现一个implicit int谎言,它将停止并放弃.

但是,您可以编写purchaseCandles方法来操作可以转换为的类型Int,并且需要该类型的参数:

def purchaseCandles[A <% Int]()(implicit age : A) = {
  val asAge : Int = age
  println(s"I'm going to buy $asAge candles!")
}
Run Code Online (Sandbox Code Playgroud)

asAge部分是强制应用隐式转换所必需的.

到目前为止,我似乎需要A在这个场景中指定类型,虽然我无法解决原因:因为不应该有其他可以隐式转换为类型的值Int(这种情况发生在全新的类型中所以,这不是无处不在Int.)但你可以这样做:

{
  implicit val guest = Monkey(10000)

  purchaseCandles[Monkey]()
}
Run Code Online (Sandbox Code Playgroud)

然而,使用implicits可能是一个坏主意!