我正在定义一些Scala隐式表达式,以使使用一组特定的不可更改的Java类变得更容易。下面的Scala代码是一个明显看起来很疯狂的简化示例,在现实世界中,我试图隐式地从猴子、树和鸭子中获取特定的资源(而不是数字年龄),以便在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()
}编译器错误,出现3次:
could not find implicit value for parameter age: Int
purchaseCandles()
^抛开这个示例代码疯狂的许多不同方面不谈,我真正的问题是:隐式值的隐式转换能否满足Scala中的隐式参数?
发布于 2013-03-15 19:37:11
简短的回答是:不。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!")
}asAge部分是强制应用隐式转换所必需的。
到目前为止,我似乎需要在这个场景中指定A的类型,尽管我不知道为什么:因为在可以隐式转换为Int的类型周围不应该有其他值(这种情况在全新的类型中也会发生,所以它不是Int的普遍存在)。但是你可以这样做:
{
implicit val guest = Monkey(10000)
purchaseCandles[Monkey]()
}然而,这种隐含的用法可能不是一个好主意!
发布于 2014-12-12 07:26:47
您实际上可以这样做:您只需将隐式转换的参数也标记为隐式:
implicit def monkey2Age(implicit monkey: Monkey): Int = monkey.bananas / 1000
implicit def tree2Age(implicit tree: Tree): Int = tree.rings
implicit def duck2Age(implicit duck: Duck): Int = duck.quacks.size / 100000这将以你想要的方式链接它们。
一如既往:当心,它也会在你不想要的地方这样做。顺便说一句,我强烈建议不要使用Int类型的隐式参数(或其隐式值)。它太普通了。(我在某种程度上假设这就是您的示例中的情况)。
https://stackoverflow.com/questions/15431278
复制相似问题