Scala和Java枚举的区别

6

我读了SO上的一篇答案,有人说Scala枚举是无用的,如果你真的需要,应该使用Java枚举。

虽然我以前使用过Java枚举,但由于我在日常工作中不编写Java代码,所以我不能说我完全理解它们。

可以有人解释一下Scala和Java枚举之间的区别以及Scala枚举的缺点所在吗?


Scala的枚举并不落后。https://dev59.com/RHzaa4cB1Zd3GeqPLRIC 它只是没有Scala的case类/对象那么方便。 - Naetmul
1个回答

4
Scala的枚举类型的主要优点是语法的规律性。
如果您想要为枚举元素添加行为,只需扩展其Val类即可。
Odersky认为它们最简单的用法是命名整数值常量。他在邮件列表上首次承诺改进支持。
但是我最近 使用它们来替换字符串列表,因为值的集合是位集,比查找字符串集合更好。
而不是:
val stuff = List("foo", "bar", "baz")

object stuff extends Enumeration { val foo, bar, baz = Value }

或者

scala> object stuff extends Enumeration { val foo, bar, baz = Value }
defined object stuff

scala> val junk = new Enumeration { val foo, bar, baz = Value }
junk: Enumeration{val foo: this.Value; val bar: this.Value; val baz: this.Value} = 1

scala> stuff.values contains junk.foo
<console>:10: error: type mismatch;
 found   : junk.Value
 required: stuff.Value
              stuff.values contains junk.foo
                                         ^

行为:

scala> trait Alias { def alias: String }
defined trait Alias

scala> object aliased extends Enumeration {
     | class Aliased extends Val with Alias {
     |   def alias = toString.permutations.drop(1).next }
     | val foo, bar, baz = new Aliased }
defined object aliased

scala> abstract class X { type D <: Enumeration
     | def f(x: D#Value) = x match { case a: Alias => a.alias
     |   case _ => x.toString } }
defined class X

scala> class Y extends X { type D = aliased.type }
defined class Y

scala> new Y().f(aliased.bar)
res1: String = bra

scala> new Y().f(stuff.foo)
<console>:13: error: type mismatch;
 found   : stuff.Value
 required: aliased.Value
              new Y().f(stuff.foo)
                              ^

scala> new X { type D = junk.type }.f(junk.foo)
warning: there was one feature warning; re-run with -feature for details
res4: String = foo

ValueSet 是一个位集:

scala> stuff.values contains aliased.bar
<console>:11: error: type mismatch;
 found   : aliased.Aliased
 required: stuff.Value
              stuff.values contains aliased.bar
                                            ^

scala> stuff.foo + aliased.bar
<console>:11: error: type mismatch;
 found   : aliased.Aliased
 required: stuff.Value
              stuff.foo + aliased.bar
                                  ^

scala> stuff.foo + stuff.bar
res8: stuff.ValueSet = stuff.ValueSet(foo, bar)

今天在Scala中似乎有效的其他内容:

scala> def f[E <: Enumeration](e: E)(v: e.Value) = e.ValueSet.empty + v
f: [E <: Enumeration](e: E)(v: e.Value)e.ValueSet

scala> f(stuff)(stuff.foo)
res14: stuff.ValueSet = stuff.ValueSet(foo)

scala> def g[E <: Enumeration](e: E)(a: Any) = a match { case _: e.Value => true case _ => false }
g: [E <: Enumeration](e: E)(a: Any)Boolean

scala> g(stuff)(stuff.foo)
res15: Boolean = true

scala> g(stuff)(junk.foo)    // checking outer pointers
warning: there was one feature warning; re-run with -feature for details
res16: Boolean = false

scala> g(stuff)(aliased.foo)
res17: Boolean = false

看起来Scala对Java枚举类型不是完全友好

scala> Thread.State.NEW.ordinal
[snip]
scala.reflect.internal.FatalError: 
  Unknown type: <notype>(NEW), <notype> [class scala.reflect.internal.Types$UniqueConstantType, class scala.reflect.internal.Types$NoType$] TypeRef? false
     while compiling: <console>
        during phase: icode
     library version: version 2.11.2
    compiler version: version 2.11.2
  reconstructed args: 

  last tree to typer: Apply(method ordinal)
       tree position: line 8 of <console>
            tree tpe: Int
              symbol: final method ordinal in class Enum
   symbol definition: final def ordinal(): Int (a MethodSymbol)
      symbol package: java.lang
       symbol owners: method ordinal -> class Enum
           call site: constructor $read$$iw$$iw in package $line4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接