4

I've read this and this, but I still don't understand the (idiomatic) equivalent way to do this in Scala

enum Status { 
    OK(1, "Ok", "Okay"),
    NOT_OK(5, "Not Ok", "Not Okay")
    BAD(10, "Bad", "Run for your life")

    int code;
    String name;
    String description; // custom fields

    Status(int code, String name, String description) {
        this.code = code;
        this.name = name;
        this.description = description;
    }
}

class Main {
    public static void main(String[] args) {
        for(Status status : Status.values) { // iterate through them
            doStuff(status);
        }
    }

    private doStuff(Status status) {
        System.out.println(status.description);
        // and more
    }
}
Community
  • 1
  • 1
Paul Draper
  • 78,542
  • 46
  • 206
  • 285
  • I think the question title is wrong – kan Feb 03 '14 at 20:39
  • 1
    I don't understand what etag values and nginx have to do with Scala enumerations. An etag is a server generated hash value that an HTTP client can use to detect if content has changed. – David H. Bennett Feb 03 '14 at 20:39
  • Oh man, that was embarrassing. I was going to ask a question "Can Nginx ETag proxied content?" last week, but I discarded it after writing just the title. When asked this question, it apparently was already set as the title. – Paul Draper Feb 03 '14 at 20:44

3 Answers3

10

In Scala you can create a Enumeration structure which is close to "enum" from Java. Basically, what you need to do is just to extend a scala.Enumeration class and to extend a Val class if you need a more complicated class as a enum. Otherwise, you can use default Val class which takes Int or String or Both. Below, is a Scala version of your Java code.

object Status extends Enumeration {

  case class StatusVal(code: Int, name: String, description: String) extends Val

  val OK = StatusVal(1, "Ok", "Okay")
  val NOT_OK = StatusVal(1, "Not Ok", "Not Okay")
  val BAD = StatusVal(1, "Bad", "Run for your life")
}

object Application extends App {
  Status.values foreach (s => println(s.asInstanceOf[StatusVal].description))
}
kikulikov
  • 2,512
  • 4
  • 29
  • 45
4

There is no direct mapping between case class and enumerations or something really close to enumerations either. But you can implement similar logic this way:

case class Status(code: Int, name: String, descr: String)
object Status {
 val OK = Status(1, "Ok", "Okay"),
 val NOT_OK = Status(5, "Not Ok", "Not Okay")
 val BAD = Status(10, "Bad", "Run for your life")
}

Then if you want you can place it in some list called values:

import Status._
val values = List(OK, NOT_OK, BAD)

and then do your stuff:

values.foreach(doStuff)

The result would be the same like in Java version

If you need to execute different actions which depends on type of Status, then you can go with pattern matching:

sealed trait Status
case class OK(code: Int, name: String, descr: String) extends Status
case class Not_Ok(code: Int, name: String, descr: String) extends Status
case class Bad(code: Int, name: String, descr: String) extends Status

then in your doStuff function use pattern matching, e.g:

def doStuff(status: Status) = status match {
  case OK(c, n, d) => // some code..
  // some code for other cases
}

val values = List(OK(1, "Ok", "Okay"), Not_Ok(5, "Not Ok", "Not Okay"), Bad(10, "Bad", "Run for your life"))

value.foreach(doStuff)
4lex1v
  • 21,367
  • 6
  • 52
  • 86
  • 2
    I prefer your `sealed trait Status` approach, but I'd use `case object` instead of `case class` to declare the three "enum" values. – DaoWen Feb 04 '14 at 03:13
  • @DaoWen in case of case objects extending a trait or a class, you won't have implicit apply/unapply for pattern matching. – 4lex1v Feb 04 '14 at 06:45
0

You could use sealed class + case object. The only part you can't get with this approach is method values, but you could use this answer to implement method values like this:

sealed class Status(val code: Int, val name: String, val description: String)
object Status {
  def values: Set[Status] = macro SealedExample.values_impl[Status]

  case object OK extends Status(1, "Ok", "Okay")
  case object NOT_OK extends Status(5, "Not Ok", "Not Okay")
  case object BAD extends Status(10, "Bad", "Run for your life")
}

def doStuff(status: Status) = println(status.description)

for {s <- Status.values}
  doStuff(s)
// Okay
// Not Okay
// Run for your life
Community
  • 1
  • 1
senia
  • 37,745
  • 4
  • 88
  • 129