斯卡拉:含蓄地传递一个隐含参数,另一个明确。可能吗?

问题描述 投票:26回答:5

让我们考虑的功能:

def foo(implicit a:Int, b:String) = println(a,b)

现在,让我们假设有一个范围的隐含StringIntimplicit val i1=1),但我们想传递一个其他的,不隐Intval i2=2)明确地foo

我们怎样才能做到这一点?可能吗?谢谢阅读。

scala implicit
5个回答
31
投票

我可以补充的是:

def foo(implicit a: Int, b: String) = println(a, b)
implicit val i1 = 1
implicit val s = ""
val i2 = 2
foo(i2, implicitly[String])

5
投票

如果你的方法有很多隐含参数(有时我在我的项目),你有时只想指定其中明确之一,并让其他人得到了解决含蓄,你可以写implicitly每隔参数一样显示在我的其他答案。但有时你会改变该方法或明确的参数在参数列表中,那么你可以用下面的结构更易读客户端代码的签名:

假设你有一些类型及其隐含的虚拟对象:

trait I1; implicit object I1 extends I1
trait I2; implicit object I2 extends I2
trait I3; implicit object I3 extends I3
trait I4; implicit object I4 extends I4
trait I5; implicit object I5 extends I5
trait I6; implicit object I6 extends I6

现在你使用了这些implicits你的方法foo1

def foo1(implicit i1: I1, i2: I2, i3: I3, i4: I4, i5: I5, i6: I6) {
  println(i1, i2, i3, i4, i5, i6)
}

现在,你经常要明确指定i4: I4。所以,你写的:

val i4 = new I4 {}
foo1(implicitly, implicitly, implicitly, i4, implicitly, implicitly)

丑陋! 用下面的(应放置在狭小的范围,方法foo2或许改名)包装所有implicits:

object Implicits {
  def apply(i4: I4)(implicit i1: I1, i2: I2, i3: I3, i5: I5, i6: I6) = new Implicits(i1, i2, i3, i4, i5, i6)
  implicit def applying(implicit i1: I1, i2: I2, i3: I3, i4: I4, i5: I5, i6: I6) = new Implicits(i1, i2, i3, i4, i5, i6)
}
class Implicits(val i1: I1, val i2: I2, val i3: I3, val i4: I4, val i5: I5, val i6: I6)

和相关方法foo2

def foo2(implicit implicits: Implicits) = {
  import implicits._
  println(i1, i2, i3, i4, i5, i6)
}

您现在可以调用foo2而不是foo1方式如下:

locally {
  foo2 // using implicit dummy objects I1, ..., I6 from above
  // or with explicit I4:
  val i4 = new I4 {}
  foo2(Implicits(i4))
}

4
投票
  1. 显式调用foo(i2, s1)但你失去了使用implicit String的益处
  2. 定义def foo1(a: Int)(implicit b: String)=foo(a,b)和你打电话foo1(i2)

2
投票

您可以创建一个新的内部范围和它定义一个新的implicit val。其优点是比当你有多个函数调用,这样就可以覆盖隐含的所有他们中的一个在同一个地方:

def foo(implicit a:Int, b:String) = println(a,b).

implicit val i = 1
implicit val s = ""

foo // call with original implicits

{
  implicit val i = 2

  foo // call with a new Int implicit

  foo // call with a new Int implicit again

}

注:新的隐必须具有相同的变量名作为原单,所以它隐藏它,否则你将得到不明的隐性价值编译错误。


0
投票

我知道这是一个老问题,但它仍然可能是有趣。一个很好的办法做到这一点是使用隐含的默认值:

scala> def foo(a: Int = implicitly[Int], b: String = implicitly[String]) = println(a,b)

scala> foo()
(10,boo)

scala> foo(50)
(50,boo)

scala> foo(b="bar")
(10,bar)
© www.soinside.com 2019 - 2024. All rights reserved.