scala - 如何使用 scala 类成员名称作为变量

标签 scala class var

在 scala 中,有没有办法访问类成员,但成员名称是 var? 下面是一个代码片段,有一个名为“one_star”的类成员。我有一个变量,其值为“one_star”,我想将此变量用作“案例类”的成员名称。

case class Features(
  // star about
  var one_star: String = "0",
  var two_star: String = "0",
  var three_star: String = "0",
  var four_star: String = "0",
  var five_star: String = "0"

  // other about
)

object Features {
  def apply(): Features = {
    val features = new Features()
    var testVar = "one_star"
    features.${testVar} = "1"
    features
  }
}

最佳答案

如果您想动态更改字段名称,即提供类变量名作为值,找到匹配给定变量名的字段,最后更改该字段的值,有几种方法:简单的一种是使用模式匹配来检查字段值和自己更改实例值并返回实例。但是,它可能会非常困惑,因为您需要处理类中定义的每个字段,如果您有很多字段,它可能会非常麻烦。因此,您将需要一些通用的方法来解决这个问题。

另一种方法是使用 scala 反射。 Scala 反射是为此而设计的,即在运行时像您的情况一样以更通用的方式修改您的代码。以下是更改给定字段名称的实例值的代码片段。

  case class Features(
                       // star about
                       var one_star: String = "0",
                       var two_star: String = "0",
                       var three_star: String = "0",
                       var four_star: String = "0"

                       // other about
                     ) {
    def copyInstance(variableName: String, value: String): Features = {
      // 1. Initialize Features instance
      val instance = Features()

      // 2. Import scala reflection api.
      import scala.reflect.runtime.{universe => ru}

      // 3. Get the mirror of instance of Features class.
      // Mirror will reflect to instance of Features case class, and we will use this instance mirror to modify its fields value.
      val instanceMirror = ru.runtimeMirror(instance.getClass.getClassLoader).reflect(instance)

      // 4. Now, Get the field whose value need to be changed - i.e. name you provide - variableName.
      val field = ru.typeOf[Features].decl(ru.TermName(variableName)).asTerm

      // 5. Get the mirror for that field so that we can read and write to this field.
      val fieldMirror = instanceMirror.reflectField(field)

      // 6. Finally, set the value to this field.
      fieldMirror.set(value)

      // 7. Return the changed instance.
      instance
    }
  }

  val features = Features()
  val changedFeatures = features.copyInstance("one_star", "changed")

  println(features)
  println(changedFeatures)

//Result
Features(0,0,0,0)
Features(changed,0,0,0)

另请注意,对于提供了无效变量名称和值的情况,您可能需要处理异常。此外,如果您的案例类包含 >22 个字段参数,则案例类的某些功能将不可用。

关于scala - 如何使用 scala 类成员名称作为变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45626169/

相关文章:

actionscript-3 - Actionscript 3类的工作方式

Javascript Shadowing - 如果您尝试使用 VAR 关键字更改已存在的全局变量,则会产生影响

postgresql - Slick 与 PostgreSQL Scala SBT Intellij IDEA

javascript - 如果我可以随时向对象插入任何属性,那么在 javascript 中创建类有什么用

scala - 如何在 Windows 中启用 SBT 远程调试?

php - 如何在 PHP 中为类方法起别名?

javascript - 如何使用javascript查找可被多个数字整除的数字

javascript - 请解释两个程序之间的输出差异

bash - 为什么 Scala 使用反向 shebang (!#) 而不是仅仅将解释器设置为 scala

scala - Scala 中使用 mongoDB 执行 CRUD 操作有哪些方式