我讀an answer on SO where someone said that scala enumerations are useless,如果你真的需要,你應該只使用java枚舉。scala和java枚舉之間的區別
雖然我之前使用過java枚舉,但我不能說我完全理解它們,因爲我在日常工作中不用java代碼。
有人可以解釋scala和java枚舉之間的區別,以及scala枚舉中的缺點究竟在哪裏?
我讀an answer on SO where someone said that scala enumerations are useless,如果你真的需要,你應該只使用java枚舉。scala和java枚舉之間的區別
雖然我之前使用過java枚舉,但我不能說我完全理解它們,因爲我在日常工作中不用java代碼。
有人可以解釋scala和java枚舉之間的區別,以及scala枚舉中的缺點究竟在哪裏?
Scala枚舉的主要弱點是難以向它們添加方法和字段。在Java中,使用枚舉作爲具有固定數量實例的Class(例如,爲什麼它們是實現單例的理想選擇)是微不足道的。
然而,在斯卡拉枚舉只是一組可能的值;向他們添加方法和領域是一個更加棘手的過程。所以如果你想要從枚舉中除了微不足道的行爲之外,Java枚舉是一個更方便的工具。
例如一個Java枚舉可能是這樣的:
public enum Month{
january(31),
february(28),
...
december(31);
public final int daysInMonth;
Month(int daysInMonth){
this.daysInMonth = daysInMonth;
}
}
然而,在Scala中,你就必須做到這一點:
object Month extends Enumeration{
protected case class Val(val daysInMonth:Integer) extends super.Val{}
implicit def valueToMonth(x:Value) = x.asInstanceOf[Val]
val january = Val(31)
val february = Val(28)
....
}
這看起來不那麼糟糕的瑣碎像這樣的例子,但它確實添加了一些令人困惑的語法,並增加了另一個類的開銷,這將需要隱式轉換爲enum的大多數用途。
我在Java枚舉中看到的主要優點是,你完全可以寫出你的意思;一個枚舉,其上有一些方法和字段。在斯卡拉,你寫的東西不是你的意思;您需要創建一個枚舉,其中包含一個具有所需方法和字段的類,並且還定義從該類到枚舉的轉換。這是表達同樣想法的一種不那麼習慣的方式。
正如所指出的in the comments,斯卡拉確實提供Case Classes,它可以在許多情況下作爲枚舉的替代品,並且有更清晰的語法。但是在某些情況下,Case Classes還不夠(例如當你想迭代所有值時),所以常規的枚舉仍然有它們的位置。 更正:使用宏確實可以迭代Case Classes,但這樣做有其自身增加的複雜性,而枚舉(在Scala和Java中)則更容易迭代。
值得注意的是,第三種解決方案是使用大小寫對象,[在這裏討論](http://stackoverflow.com/questions/1898932/case-classes-vs-enumerations-in-scala)。 – 2014-08-29 17:23:41
和密碼特徵的迭代可能與宏 - http://stackoverflow.com/questions/13671734/iteration-over-a-sealed-trait-in-scala – Gavin 2014-08-29 20:03:56
Scala的Enumeration的主要優點是語法的規律性。
如果要將行爲添加到枚舉的元素,只需擴展它的Val
類即可。
Odersky將它們作爲最簡單的用例命名爲int值常量。他剛剛在郵件列表上承諾,第一次,改善的支持即將到來。
但我recentlyused他們替換字符串的列表,因爲值的集合是一個位集,比一組查詢字符串更好。
而不是
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
爲not entirely friendly to Java enums:
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
Scala的枚舉是不是落後。 http://stackoverflow.com/questions/21537148/scala-java-enumerations它只是不如斯卡拉的案例類/對象。 – Naetmul 2014-08-29 15:35:29