【问题标题】:Scala: List of constants with individual accessScala:具有单独访问权限的常量列表
【发布时间】:2017-03-31 05:47:46
【问题描述】:

我是 scala 的新手,我需要一个结构,我可以在其中轻松添加新的个人可访问常量并遍历所有常量。 像这样的:

object Constants {
    val A = Something(...)
    val B = Something(...)
    val C = Something(...)
    // ...

    val listOfConstants = (A, B, C, ...)
}

但无需手动将常量添加到列表中。 我考虑了一个 Map 但这会使访问常量变得更加困难 我最终写了这个:

def getElements[T : ClassTag](c : Any) : Set[T] = {
    var result : Set[T] = Set()
    for (field <- c.getClass.getDeclaredFields) {
        field.setAccessible(true)
        field.get(c) match {
            case t: T => result += t
            case _ =>
        }
    }
    result
}

然后对这样的结构使用以下行

val listOfConstants = getElements[Something](Constants)

这是一个肮脏的解决方案吗?有更好的选择吗?

【问题讨论】:

    标签: scala


    【解决方案1】:

    您可以使用 scala 的默认 Enumeration,但它有自己的 caveats。我知道的最好的枚举库是Enumeratum。它允许你写这样的东西:

    object MyEnum extends Enum[Something] {
    
      val values = findValues
    
      case object A extends Something
      case object B extends Something
      case object C extends Something
      case object D extends Something
    
    }
    

    findValues 是一个宏,它会在编译时自动查找Something(在MyEnum 内)的所有子对象。

    使用 SBT 添加这个库:

    libraryDependencies += "com.beachape" %% "enumeratum" % "1.4.0"
    

    【讨论】:

      【解决方案2】:

      尝试枚举,例如http://www.scala-lang.org/api/current/scala/Enumeration.htmlHow to model type-safe enum types?。您还可以用 Java 编写枚举并在 Scala 中使用它

      例如,这里有一个用 Java 定义的枚举,您可以在 Scala 中使用它 - 并附带一个包含所有可能值的映射,因此您可以通过键获取、迭代值等。值的映射是构建的自动,所以不需要手动维护。

      import java.util.Collections;
      import java.util.Map;
      import java.util.HashMap;
      
      /**
       * Demonstrates parsing of an enum from the contained value
       */
      public enum WithFrom implements Something {
          TWO("one plus 1"), SIX("two plus 4");
      
          WithFrom(String expr) {
              this.expr = expr;
          }
      
          private final String expr;
      
          public static final Map<String, WithFrom> fromValue = Collections
                  .unmodifiableMap(new HashMap<String, WithFrom>() {
                      private static final long serialVersionUID = 7205142682214758287L;
      
                      {
                          for (WithFrom wf : WithFrom.values()) {
                              put(wf.expr, wf);
                          }
                      }
                  });
      }
      

      【讨论】:

      • 感谢您的回答,但在我的情况下,Something 是一种抽象类型,其中 A、B、C... 可以是各种子类型。据我了解枚举无法扩展。
      • Java 枚举可以实现一个接口。这会有帮助吗?
      【解决方案3】:

      您可以创建一个Enumeration 并使用它的values: ValueSet 方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-23
        • 1970-01-01
        • 2021-11-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-25
        相关资源
        最近更新 更多