将字段名称获取为字符串

时间:2018-10-25 00:27:03

标签: scala reflection

我有一个特征,它会覆盖toString以打印所有字段的值:

/**
  * Interface for classes that provide application configuration.
  */
trait Configuration {
  /** abstract fields defined here. e.g., **/
  def dbUrl: String

  /**
    * Returns a list of fields to be excluded by [[toString]]
    */
  protected def toStringExclude: Seq[String]

  /**
    * Returns a String representation of this object that prints the values for all configuration fields.
    */
  override def toString: String = {
    val builder = new StringBuilder
    val fields = this.getClass.getDeclaredFields
    for (f <- fields) {
      if (!toStringExclude.contains(f.getName)) {
        f.setAccessible(true)
        builder.append(s"${f.getName}: ${f.get(this)}\n")
      }
    }
    builder.toString.stripSuffix("\n")
  }
}

一个具体的类目前看起来像这样:

class BasicConfiguration extends Configuration {
  private val config = ConfigFactory.load

  override val dbUrl: String = config.getString("app.dbUrl")

  /**
    * @inheritdoc
    */
  override protected def toStringExclude: Seq[String] = Seq("config")
}

问题是,如果在某个时候重命名了config,那么IDE只会丢失"config"中的toStringExclude,因为它只是一个字符串。因此,我正在尝试找到一种将字段名称作为字符串获取的方法,例如getFieldName(config)

2 个答案:

答案 0 :(得分:1)

我不喜欢这样,我不会这样做,但这是这样:

class BasicConfiguration extends Configuration {

  private val config = ConfigFactory.load

  override val dbUrl: String = config.getString("app.dbUrl")

  private val excludeFields: Set[Any] = Set(config)

  override protected val toStringExclude: Seq[String] = {
    this.getClass
      .getDeclaredFields
      .filter(field => Try(field.get(this)).fold(_ => false, a => excludeFields.contains(a)))
      .map(_.getName)
      .toList
  }

}

答案 1 :(得分:1)

使用https://github.com/dwickern/scala-nameof

import com.github.dwickern.macros.NameOf._

class BasicConfiguration extends Configuration {
  private val config = ConfigFactory.load

  override val dbUrl: String = config.getString("app.dbUrl")

  /**
    * @inheritdoc
    */
  override protected def toStringExclude: Seq[String] = Seq(nameOf(config))
}