是否可以在Scala中将"this"作为隐式参数传递?

Jea*_*let 9 scala implicit

假设我想包装可以使用try-catch块抛出异常的代码,该块记录异常并继续.就像是:

loggingExceptions {
  // something dangerous
}
Run Code Online (Sandbox Code Playgroud)

理想情况下,我想用于记录调用对象上定义的Logger(如果有的话)(如果没有,则会产生编译时错误).我喜欢定义这样的东西:

def loggingExceptions[L <: { def logger: Logger }](work: => Unit)(implicit objectWithLogger: L): Unit = {
  try {
    work
  } catch {
    case t: Exception => objectWithLogger.logger.error(t.getMessage)
  }
}
Run Code Online (Sandbox Code Playgroud)

其中objectWithLogger会以某种方式"神奇地"在客户端代码中扩展为"this".这个(或类似的东西)可能吗?

psp*_*psp 12

事实上,它可以按照您的意愿完成.其他的回答者投降得太快了.没有白旗!

package object foo {
  type HasLogger = { def logger: Logger }
  implicit def mkLog(x: HasLogger) = new {
    def loggingExceptions(body: => Unit): Unit =
      try body
      catch { case ex: Exception => println(ex) }
  }
}

package foo {
  case class Logger(name: String) { }

  // Doesn't compile:
  // class A {
  //   def f = this.loggingExceptions(println("hi"))
  // }
  // 1124.scala:14: error: value loggingExceptions is not a member of foo.A
  //         def f = this.loggingExceptions(println("hi"))
  //                      ^
  // one error found  

  // Does compile
  class B {
    def logger = Logger("B")
    def f = this.loggingExceptions(println("hi"))
    def g = this.loggingExceptions(throw new Exception)
  }
}

object Test {
  def main(args: Array[String]): Unit = {
    val b = new foo.B
    b.f
    b.g
  }
}

// output
//
// % scala Test
// hi
// java.lang.Exception
Run Code Online (Sandbox Code Playgroud)

  • 你的负面清单总结为"我宁愿解决另一个问题." 嗯,是的,不是我们所有人. (5认同)
  • 示例为+1.这个_可以完成,但这是不可取的.它不会区分日志记录问题以及日志记录特征,需要"隐式魔法",并且会产生不必要的编译时(隐式搜索)和运行时(反射)开销.该实现隐藏了隐式转换需要在范围内的事实,并且在更现实的代码库中,这将需要客户端代码中的import语句. (2认同)