在 Scala 中,如何在伴随对象中定义隐式 value/parameter?

In Scala, how to define a implicit value/parameter in companion object?

我看到下面的代码 Link

abstract class SessionFactory {

  protected[squery] def createConnection(): Connection

  def createSession(): Session = new Session(this)

  def withSession[T](f: Session => T): T = {
    val s = createSession()
    try { f(s) } finally s.close()
  }

  def withSession[T](f: => T): T =
    withSession { s: Session => SessionFactory.dyn.withValue(s)(f) }
}

object SessionFactory {

  private val dyn = new DynamicVariable[Session](null)

  implicit def getThreadSession: Session = {
    val s = dyn.value
    if(s eq null)
      throw new SQLException("No implicit thread session available; getThreadSession() can only be used within a withSession block")
    else s
  }
}

我不知道 def withSession[T](f: => T): T 如何获得 s:Session 的值,所以我尝试在一个简单的片段中重现 implicit 的这种用法:

class printTest {
  def printWithParameter(s:String) = println(s)
  def printWithImplicit = printWithParameter(s:String)
}

object printTest {
  implicit val sp:String = "implicit value"
  implicit def getString:String = "implicit def"
}

val pt = new printTest()
pt.printWithImplicit

但是 printTest 不起作用,编译器说:

Error:(3, 47) not found: value s
  def printWithImplicit = printWithParameter(s:String)
                                             ^

有人对此有想法吗?

这就是你得到

的原因
Error:(3, 47) not found: value s
  def printWithImplicit = printWithParameter(s:String)
                                             ^

是因为你定义了一个名为printWithImplicit的函数,它不带参数,return Unit。可以显式写成:def printWithImplicit(): Unit

因为它没有参数,所以它的函数体,在这个例子中,printWithParameter(s:String),找不到s

的定义

回到你的问题。

您需要 import printTest.sp

之前
val pt = new printTest()
pt.printWithImplicit

我把你的例子简化了一点:

class printTest {
  def printWithParameter(s:String) = println(s)
  def printWithImplicit(implicit s:String) = printWithParameter(s)
}

object printTest {
  implicit val sp:String = "implicit value"
}

import printTest.sp
val pt = new printTest()
pt.printWithImplicit

你被误导了。未使用隐式,因为该方法 不是 获取 Session 的值。让我们回顾一下:

def withSession[T](f: => T): T =
  withSession { s: Session => SessionFactory.dyn.withValue(s)(f) }

因此,它采用类型为 Tf,按名称传递(也就是说,它在使用时计算,而不是在调用 withSession 时计算)。然后它调用 withSession 将函数从 Session 传递到 T。它 创建 Session,它 请求 Session,可以这么说。那么让我们看看它叫什么:

def withSession[T](f: Session => T): T = {
  val s = createSession()
  try { f(s) } finally s.close()
}

这里它需要一个从SessionT的函数(这将是s: Session => SessionFactory.dyn.withValue(s)(f)),创建一个Session,然后使用该会话调用传递的函数。会话创建只是一个 new Session(this),因此没有任何隐式被使用。