在Scala中,如何在伴随对象中定义隐式值/参数?

时间:2015-05-11 08:57:44

标签: scala session implicit

我在下面的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)
                                             ^

有没有人有这方面的想法?

2 个答案:

答案 0 :(得分:2)

这个原因你得到了

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

是因为您定义了一个名为printWithImplicit的函数,该函数不带参数并返回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

答案 1 :(得分:2)

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

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

因此,它需要f类型T,按名称传递(即,在使用时进行评估,而不是在调用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),所以没有任何隐含的使用。