如何在Scala中定义错误类型?

如何在Scala中定义错误类型?,scala,enums,Scala,Enums,假设我为Scala应用程序定义了错误。我希望它们是错误、警告和正常。我希望错误和警告包含人类可读的文本消息 我还想分配数字代码(0-表示Ok,1-表示Warning,2-表示Error),例如,在错误列表中查找最严重的错误 因此,我将这个错误定义如下: object MyErrors { abstract sealed case class MyError(code: Int, maybeMessage: Option[String]) object Ok extends MyErr

假设我为Scala应用程序定义了错误。我希望它们是
错误
警告
正常
。我希望
错误
警告
包含人类可读的文本消息

我还想分配数字代码(0-表示
Ok
,1-表示
Warning
,2-表示
Error
),例如,在错误列表中查找最严重的错误

因此,我将这个错误定义如下:

object MyErrors { abstract sealed case class MyError(code: Int, maybeMessage: Option[String]) object Ok extends MyError(0, None) final case class Warning(message) extends MyError(1, Some(message)) final case class Error(message) extends MyError(2, Some(message)) } 对象MyErrors{ 抽象密封案例类MyError(代码:Int,maybeMessage:Option[String]) 对象Ok扩展MyError(0,无) 最终案例类警告(消息)扩展了MyError(1,部分(消息)) 最后一个案例类错误(消息)扩展了MyError(2,Some(消息)) }
这有意义吗?您将如何实施它?

我认为有几个问题:

  • 不能扩展案例类。考虑<代码>密封特性< /代码>或一个简单的<代码>抽象类< /代码>
  • 为什么它们都包含在
    MyErrors
    对象中
  • 您真的需要
    Int
    字段吗?您可以使用模式匹配进行过滤
  • Ok
    作为
    MyError
    的实例在语义上看起来是错误的。我宁愿使用
    状态
  • 选择的问题,但我会为
    errorstatus
  • 在你设计之前,你有没有考虑过或者作为备选方案?
    这就是我认为你想要做的:

    object MyErrors extends Enumeration {
      val Ok = Value("ok", 0)
      val Warning = Value("warning", 1)
      val Error = Value("error", 2)
    
      class TypeVal(val name: String, val code: Int) extends Val(nextId, name)
    
      protected final def Value(name: String, code: Int) = new TypeVal(name, code)
    
      sealed case class MyError(error: TypeVal, maybeMessage: Option[String])
    
      def ok(msg: Option[String] = None) = new MyError(Ok, msg)
      def error(msg: Option[String] = None) = new MyError(Error, msg)
      def warning(msg: Option[String] = None) = new MyError(Warning, msg)
    
    }
    
    用作:

    val e = MyErrors.error() 
    // or
    val f = MyErrors.ok(Option("Don't worry, be happy"))
    f.error.code // Int = 0
    f.maybeMessage // Option[String] = Some(Don't worry, be happy)
    

    很明显,它可以被清理很多。但是它应该会让你继续前进。

    根据Nicolas关于将你的类型重命名为
    状态的建议,这里有一些代码和其他细节:

    sealed trait Status {
      def code: Int
    }
    object Status {
      case object Ok extends Status {
        val code = 0
      }
      sealed trait WithMessage extends Status {
        def message: String
      }
      case class Warning (message: String) extends WithMessage {
        val code = 1
      }
      case class Error (message: String) extends WithMessage {
        val code = 2
      }
    }
    
    然后您可以这样使用它:

    scala> Status.Ok
    res0: Status.Ok.type = Ok
    
    scala> Status.Warning("blabla")
    res1: Status.Warning = Warning(blabla)
    
    scala> Status.Error("blabla").code
    res2: Int = 2
    

    (2*警告==错误)
    ?:)如果不是,则算术数据类型的概念有点过于具体。也许像日志记录这样的粗略分组(严重、严重、致命等)更好,并且可以通过继承来建模。另外:类
    可能对您有用。之后,如果他有更多错误值,则可能会有用。。。例如,要使用大于
    x
    的代码过滤每个错误。请查看Scala的解析器组合器如何对结果进行编码,这些结果具有类似的层次结构。@Nicolas最好删除数字代码,而使用排序/排序。@paradigmatic我完全同意。我只需要弄清楚如何添加
    排序
    .Re:5,这样它就不再是代数类型了。@missingfakt或不需要:
    密封特征状态
    -
    密封特征错误状态扩展状态
    -然后
    对象
    /
    案例类
    es…@Nicolas:虽然你的批评是有效的,这不是问题的答案。@Nicolas,是的,这不是ADT。