Scala/Java enumerations

三世轮回 提交于 2019-12-10 15:58:22

问题


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

回答1:


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



回答2:


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)



回答3:


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


来源:https://stackoverflow.com/questions/21537148/scala-java-enumerations

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!