【问题标题】:Scala/Java enumerationsScala/Java 枚举
【发布时间】:2014-02-27 12:24:23
【问题描述】:

我已阅读 thisthis,但我仍然不明白在 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
    }
}

【问题讨论】:

  • 我觉得题名不对
  • 我不明白 etag 值和 nginx 与 Scala 枚举有什么关系。 etag 是服务器生成的哈希值,HTTP 客户端可以使用它来检测内容是否已更改。
  • 天哪,太尴尬了。我正要问一个问题“Nginx ETag 可以代理内容吗?”上周,但我只写了标题就放弃了它。当被问到这个问题时,它显然已经被设置为标题。

标签: java scala enums idioms


【解决方案1】:

案例类和枚举之间没有直接的映射关系,也没有真正接近枚举的东西。但是你可以这样实现类似的逻辑:

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

如果你愿意,你可以把它放在一些叫做值的列表中:

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

然后做你的事情:

values.foreach(doStuff)

结果与Java版本相同

如果您需要根据状态类型执行不同的操作,那么您可以使用模式匹配:

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

然后在你的 doStuff 函数中使用模式匹配,例如:

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)

【讨论】:

  • 我更喜欢您的sealed trait Status 方法,但我会使用case object 而不是case class 来声明三个“枚举”值。
  • @DaoWen 如果 case 对象扩展了一个 trait 或一个类,你将不会隐式地应用/取消应用模式匹配。
【解决方案2】:

在 Scala 中,您可以创建一个接近 Java 的“枚举”的枚举结构。基本上,你需要做的只是扩展一个scala.Enumeration class 并扩展一个 Val 类,如果你需要一个更复杂的类作为枚举。否则,您可以使用采用 Int 或 String 或 Both 的默认 Val 类。下面是 Java 代码的 Scala 版本。

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

【讨论】:

  • 您的意思是使用 1 作为每个 StatusVal 的 ID 吗?另外,StatusVal 扩展 Val(code, name) 会更好吗?
  • @mrog,不,1 只是一个错字。您可以使用任何 Int。
【解决方案3】:

您可以使用sealed class + case object。使用这种方法唯一不能得到的部分是方法values,但您可以使用this answer 来实现方法values,如下所示:

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

【讨论】:

    猜你喜欢
    • 2015-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-10
    • 2011-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多