Java Enums
For an enum class Counter
would be a better name than Counters
- each enum value represents a singular counter.
When javac compiles an enum
class, it:
- compiles to a normal java class (E.g.
Counter
) containing all of the constructors, methods, other members of the enum (if any)
each enum
value (GOOD_THING
, BAD_THING
) is made a public static
field of (1) - with class equal to the class in (1) (Counter
):
// Java Code:
class Counter {
public static Counter GOOD_THING;
public static Counter BAD_THING;
// constructors, methods, fields as defined in the enum ...
}
initialization logic in the class automatically constructs each enum
value as a singleton object
Scala Options
A. Reference Java Enum From Scala
Import Counter, refer to GOOD_THING and BAD_THING just like in java, and (if you like) additionally call Enum class methods:
// Scala Code:
import JavaSubClass.Counter;
def someDistributedTask = {
// some work here
if (terribleThing) {
loggingMethod(Counter.BAD_THING)
} else {
loggingMethod(Counter.GOOD_THING)
// more work here
}
}
// Other things you can do:
val GoodThing = Counter.valueOf("GOOD_THING")
Counter.values() foreach { // do something }
counter match {
case Counter.GOOD_THING => "Hoorah"
case Counter.BAD_THING => "Pfft"
case _ => throw new RuntimeException("someone added a new value?")
}
Advantages: Can do everything that java enumerations do, plus supports pattern matching.
Disadvanges: Because the base trait is not sealed
, any code doing pattern matching is not typed-checked to ensure exhaustive cases are covered.
B. Use Scala Enumeration
Convert java enum
to equivalent scala Enumeration
:
// Scala Code:
object Counter extends Enumeration {
type Counter = Value
val GoodThing = Value("GoodThing")
val BadThing = Value("BadThing")
}
Use it:
// Scala Code:
import someScalaPackage.Counter;
def someDistributedTask = {
// some work here
if (terribleThing) {
loggingMethod(Counter.BadThing)
} else {
loggingMethod(Counter.GoodThing)
// more work here
}
}
// Other things you can do:
val GoodThing = Counter.withName("GoodThing")
val label = Counter.BadThing.toString
Counter.values foreach { // do something }
myCounter match {
case Counter.GOOD_THING => "Bully!"
case Counter.BAD_THING => "Meh"
case _ => throw new RuntimeException("someone added a new value?")
}
Advantages: Scala's Enumeration
methods are as rich as Java Enum
's, plus supports pattern matching.
Disadvanges: Can't do everything that java enum
s do - java enum's are defined as a class with arbitrary constructors, methods and other members allowable (i.e. full OO modelling on the enum basetype). Because the base trait is not sealed
, any code doing pattern matching is not typed-checked to ensure exhaustive cases are covered.
C. Use Scala Case Classes:
Can convert enum
s directly into Case Objects (i.e. singleton objects as opposed to Case Class, which is not singleton):
sealed trait Counter
object Counter {
case object GoodThing extends Counter;
case object BadThing extends Counter;
}
Use it:
// Scala Code:
import someScalaPackage.Counter;
def someDistributedTask = {
// some work here
if (terribleThing) {
loggingMethod(Counter.BadThing)
} else {
loggingMethod(Counter.GoodThing)
// more work here
}
}
// Other things you can do:
// NO!! val GoodThing = Counter.withName("GoodThing")
val label = Counter.BadThing.toString
// NO!! Counter.values foreach { // do something }
myCounter match {
case Counter.GOOD_THING => "Bully!"
case Counter.BAD_THING => "Meh"
case _ => throw new RuntimeException("someone added a new value?")
}
- Advantage over Enumeration: each value can have a different ancestor or different mixin traits (as long as each value conforms to type Counter). Can do arbirtrarily complex OO modelling for the trait Counter and for each Value. Can then do arbitrarily complex pattern matching using all the different case object parameters for each different value. By having base trait
sealed
, any code doing pattern matching is typed-checked to ensure exhaustive cases are covered. (Not useful for your requirements).
- Disadvantage over Enumeration: don't get Enumeration methods 'for free' (i.e. values, withName, application). Can be 'fixed' by adding custom implementations to base class Counter (a bit of a contridiction, since it's manual coding...).