代码之家  ›  专栏  ›  技术社区  ›  xuhai

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

  •  3
  • xuhai  · 技术社区  · 7 年前

    在scala中,有没有方法访问类成员,但成员名称是var?

    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
      }
    }
    
    3 回复  |  直到 7 年前
        1
  •  4
  •   Ra Ka    7 年前

    i、 e.提供类变量名作为值,查找与给定变量名匹配的字段,最后更改该字段的值 ,有几种方法:简单的方法是使用模式匹配来检查字段值,自己更改实例值并返回实例。然而,由于需要处理类中定义的每个字段,所以它可能会非常混乱,如果有许多字段,那么它可能会非常麻烦。因此,您需要一些通用的方法来解决这个问题。

    另一种方法是使用 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)
    

    Exception 对于提供无效变量名和值的情况。此外,如果您的案例类包含>22个字段参数,案例类的某些功能不可用。

        2
  •  0
  •   Ruslan K.    7 年前

    class Features (
      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") {
    
      def setField(field: String, value: String): Unit = {
        field match {
          case "one_star" => one_star = value
          case "two_star" => two_star = value
          case "three_star" => three_star = value
          case "four_star" => four_star = value
          case "five_star" => five_star = value
        }
      }
    }
    
        3
  •  0
  •   ephemient    7 年前

    这可以使用 scala-reflect ,尽管在大多数情况下,我不建议这样做。

    import scala.reflect.runtime.universe._
    
    val field = typeOf[Features].decl(TermName(testVar)).asTerm.accessed.asTerm
    val mirror = runtimeMirror(classOf[Features].getClassLoader)
    mirror.reflect(features).reflectField(field).set("1")
    

    Map[String, String] 为了你们班?如此多的属性并不典型。