获取对象中调用者类的名称的最佳方法是什么?

Sah*_*een 3 scala

我可以使用这个来完成这个工作:

scala> object LOGGER {
     | def warning(msg: String)(implicit className:String) = {
     |   className
     | }
     | }
defined object LOGGER

scala> class testing {
     | lazy implicit val className = this.getClass.getName
     | def test = LOGGER.warning("Testing")
     | }
defined class testing

scala> val obj = new testing()
obj: testing = testing@11fb4f69

scala> obj.test
res51: String = testing <=======

scala> class testing2 {
     | lazy implicit val className = this.getClass.getName
     | def test = LOGGER.warning("Testing")
     | }
defined class testing2

scala> val obj2 = new testing2()
obj2: testing2 = testing2@2ca3a203


scala> obj2.test
res53: String = testing2 <=====
Run Code Online (Sandbox Code Playgroud)

我还尝试在 中使用 Thread.currentThread.getStackTraceobject LOGGER但无法让它打印函数testing中的调用类warning。还有其他方法可以做到这一点吗?

Odo*_*ois 5

动态变量

一种方法是DymamicVariable

import scala.util.DynamicVariable
object LOGGER {
  val caller = new DynamicVariable[String]("---")
  def time = new Date().toString
  def warning(msg: String) = println(s"[${caller.value} : $time] $msg")
}

trait Logging {
  def logged[T](action: => T) = LOGGER.caller.withValue(this.getClass.getName)(action)
}

class testing extends Logging {
  def test = logged {
    //some actions
    LOGGER.warning("test something")
    //some other actions
  }
}

val t = new testing

t.test
Run Code Online (Sandbox Code Playgroud)

会打印类似的东西

[测试:11 月 25 日星期三 11:29:23 MSK 2015] 测试一些东西

或者不用混合也Logging可以直接使用

class testing {
  def test = LOGGER.caller.withValue(this.getClass.getName) {
    //some actions
    LOGGER.warning("test something")
    //some other actions
  }
}
Run Code Online (Sandbox Code Playgroud)

另一种更强大但更复杂的支持方法是构建一些简单的

您可以在其他源中定义,最好在其他子项目中定义

import scala.reflect.macros.blackbox.Context
import scala.language.experimental.macros
class LoggerImpl(val c: Context) {
  import c.universe._

  def getClassSymbol(s: Symbol): Symbol = if (s.isClass) s else getClassSymbol(s.owner)

  def logImpl(msg: Expr[String]): Expr[Unit] = {
    val cl = getClassSymbol(c.internal.enclosingOwner).toString
    val time = c.Expr[String](q"new java.util.Date().toString")
    val logline = c.Expr[String](q""" "[" + $cl + " : " + $time + "]" + $msg """)
    c.Expr[Unit](q"println($logline)")
  }
}

object Logger {
  def warning(msg: String): Unit = macro LoggerImpl.logImpl
}
Run Code Online (Sandbox Code Playgroud)

现在您不需要更改测试类:

class testing {
  def test = {
    //some actions
    Logger.warning("something happen")
    //some other actions
  }
}
Run Code Online (Sandbox Code Playgroud)

并查看所需的输出。

这可能是运行时堆栈自省的非常有效的替代方案