How to model type-safe enum types?
斯卡拉没有像Java一样具有类型安全的EDCOX1 0。给定一组相关的常量,scala中表示这些常量的最佳方法是什么?
我必须说的是,例如copied跳出Scala文档由skaffman以上在实践中的效用是有有限公司(你不妨使用
为了得到一些最紧密resembling a Java
1 2 | WeekDay.valueOf("Sun") //returns None WeekDay.Tue.toString //returns Weekday(2) |
而使用以下的声明:
1 2 3 4 5 6 |
结果:你得到更多的敏感
1 2 | WeekDay.valueOf("Sun") //returns Some(Sun) WeekDay.Tue.toString //returns Tue |
www.scala-lang.org http:/ / / / /文件/文件/ enumeration.html Scala API
使用的例子
1 2 3 4 5 6 7 8 9 10 11 12 |
有许多的方式做。
1)使用的符号。它不会给你任何类型安全的,虽然,除了不接受非符号的符号是在普通。我在这里只提它的完备性。这是一个例子:在大学。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | def update(what: Symbol, where: Int, newValue: Array[Int]): MatrixInt = what match { case 'row => replaceRow(where, newValue) case 'col | 'column => replaceCol(where, newValue) case _ => throw new IllegalArgumentException } // At REPL: scala> val a = unitMatrixInt(3) a: teste7.MatrixInt = / 1 0 0 \ | 0 1 0 | \ 0 0 1 / scala> a('row, 1) = a.row(0) res41: teste7.MatrixInt = / 1 0 0 \ | 1 0 0 | \ 0 0 1 / scala> a('column, 2) = a.row(0) res42: teste7.MatrixInt = / 1 0 1 \ | 0 1 0 | \ 0 0 0 / |
2类:使用
或者,如果你需要序列化或显示它:
1 2 3 4 |
这可以用样本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | def update(what: Dimension, where: Int, newValue: Array[Int]): MatrixInt = what match { case Row => replaceRow(where, newValue) case Column => replaceCol(where, newValue) } // At REPL: scala> a(Row, 2) = a.row(1) <console>:13: error: not found: value Row a(Row, 2) = a.row(1) ^ scala> a(Dimension.Row, 2) = a.row(1) res1: teste.MatrixInt = / 1 0 0 \ | 0 1 0 | \ 0 1 0 / scala> import Dimension._ import Dimension._ scala> a(Row, 2) = a.row(1) res2: teste.MatrixInt = / 1 0 0 \ | 0 1 0 | \ 0 1 0 / |
不幸的是,它不会是accounted确保所有比赛。如果我忘了把行或列中匹配,Scala编译器不会有警告我。所以它给我一些但不是类型安全的,多为可以得到。
3)对象:案例
1 2 3 |
现在,如果我离开
1 2 3 4 5 6 |
它使用同样的方式相当多,甚至没有需要
1 2 3 4 5 6 7 8 9 10 11 | scala> val a = unitMatrixInt(3) a: teste3.MatrixInt = / 1 0 0 \ | 0 1 0 | \ 0 0 1 / scala> a(Row,2) = a.row(0) res15: teste3.MatrixInt = / 1 0 0 \ | 0 1 0 | \ 1 0 0 / |
你可能知道,那么,为什么使用"案例"在枚举对象。作为一个事实上,个案对象做多次有优势,如在这里。类的枚举,但安切洛蒂在收集方法,如元素(迭代器在Scala 2.8),它返回的迭代器,地图,flatmap、过滤器等。
这个答案是选配件奖从这篇文章在我的博客。
不需要冗长的命名方式:declaring枚举
1 2 3 4 5 6 7 |
当然,问题是,你想在这里需要保持结构的名称和VAL在同步是容易做,如果名字和Val是被在相同的线路。
你可以使用一个抽象类而不是密封的枚举,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | sealed abstract class Constraint(val name: String, val verifier: Int => Boolean) case object NotTooBig extends Constraint("NotTooBig", (_ < 1000)) case object NonZero extends Constraint("NonZero", (_ != 0)) case class NotEquals(x: Int) extends Constraint("NotEquals" + x, (_ != x)) object Main { def eval(ctrs: Seq[Constraint])(x: Int): Boolean = (true /: ctrs){ case (accum, ctr) => accum && ctr.verifier(x) } def main(args: Array[String]) { val ctrs = NotTooBig :: NotEquals(5) :: Nil val evaluate = eval(ctrs) _ println(evaluate(3000)) println(evaluate(3)) println(evaluate(5)) } } |
enumeratum刚刚发现的。它的漂亮和惊人的惊人后,它更多的是众所周知的。
广泛的研究后,做一个"枚举"选项在Scala中,一贴一个更完整的概述本域的另一个线程上的计算器。它包括一个密封的解决方案数量+案例对象"模式在《我有我的JVM的类/对象初始化顺序问题。
在Scala中,它是非常舒适的github.com http:////enumeratum lloydmeta
一个项目是非常好的例子和文档
从这个例子就应该让你感兴趣的文档
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | import enumeratum._ sealed trait Greeting extends EnumEntry object Greeting extends Enum[Greeting] { /* `findValues` is a protected method that invokes a macro to find all `Greeting` object declarations inside an `Enum` You use it to implement the `val values` member */ val values = findValues case object Hello extends Greeting case object GoodBye extends Greeting case object Hi extends Greeting case object Bye extends Greeting } // Object Greeting has a `withName(name: String)` method Greeting.withName("Hello") // => res0: Greeting = Hello Greeting.withName("Haro") // => java.lang.IllegalArgumentException: Haro is not a member of Enum (Hello, GoodBye, Hi, Bye) // A safer alternative would be to use `withNameOption(name: String)` method which returns an Option[Greeting] Greeting.withNameOption("Hello") // => res1: Option[Greeting] = Some(Hello) Greeting.withNameOption("Haro") // => res2: Option[Greeting] = None // It is also possible to use strings case insensitively Greeting.withNameInsensitive("HeLLo") // => res3: Greeting = Hello Greeting.withNameInsensitiveOption("HeLLo") // => res4: Option[Greeting] = Some(Hello) // Uppercase-only strings may also be used Greeting.withNameUppercaseOnly("HELLO") // => res5: Greeting = Hello Greeting.withNameUppercaseOnlyOption("HeLLo") // => res6: Option[Greeting] = None // Similarly, lowercase-only strings may also be used Greeting.withNameLowercaseOnly("hello") // => res7: Greeting = Hello Greeting.withNameLowercaseOnlyOption("hello") // => res8: Option[Greeting] = Some(Hello) |
多蒂(Scala的枚举支持的有3人)。检查在这里和这里。