Differences between scala and java values

I read the answer on SO where someone said that scala enums are useless , and instead you just need to use java enums if you really need to too.

Although I used java enums before, I cannot say that I fully understand them, since I do not code java during my daytime work.

Can someone explain the differences between scala and java enums, and where exactly are the flaws in scala enums?

+5
source share
2 answers

The main drawback of Scala enumerations is the difficulty of adding methods and fields to them. In Java, it is trivial to use an enumeration as a class with a fixed number of instances (which, for example, is why they are a good choice for implementing singleton).

In Scala, however, Enums is just a collection of possible meanings; adding methods and fields to them is a much more hacker process. Therefore, if you want anything other than the trivial behavior of an enumeration, Java enumerations are a much more convenient tool.

For example, a Java enumeration might look like this:

public enum Month{ january(31), february(28), ... december(31); public final int daysInMonth; Month(int daysInMonth){ this.daysInMonth = daysInMonth; } } 

However, in Scala, you will need to do this:

 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) .... } 

This doesn't look so bad in such a trivial example, but it adds some confusing syntax and adds the overhead of another class, which should be implicitly converted for most enumeration applications.

The main advantage that I see in the Java enumeration is that you write exactly what you mean; enumeration, with some methods and fields on it. In Scala, you write something other than what you mean; you need to create an enumeration that contains a class that has the methods and fields you need, and also defines the conversion from this class to an enumeration. This is a less idiomatic way of expressing the same idea.

As pointed out in the comments , Scala offers Case Classes , which can be used in many cases as an alternative to enumerations and has a cleaner syntax. But there are still situations where class classes are not enough (for example, when you want to iterate over all values), so regular enumerations still have their place. Bugfix: using macros makes it possible to iterate over Case classes, but it has its own additional complexity, while enumerations (both in Scala and Java) are much simpler to iterate.

+8
source

The main benefit of Scala Enumeration is its regular syntax.

If you want to add behavior to the elements of your enumeration, just extend its Val class.

Odersky loves them for its simplest use case as named int-valued constants. And he just promised on the mailing list for the first time that improved support is on the horizon.

But I recently used them to replace a list of strings, since a set of bit values ​​is set, better than a set of strings to search for.

Instead

 val stuff = List("foo", "bar", "baz") object stuff extends Enumeration { val foo, bar, baz = Value } 

or

 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 ^ 

Behavior:

 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 bit set:

 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) 

Other things Scala works today:

 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 doesn't seem to be quite friendly with 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 
+3
source

Source: https://habr.com/ru/post/1201425/


All Articles