Scala:在模式匹配中混合特征和案例类

发布于 2024-12-07 08:10:26 字数 1958 浏览 1 评论 0原文

我想匹配一些案例类别。如果我不认识它们,我想匹配类必须扩展的指定特征。这看起来像

trait Event  //root trait
trait Status extends Event  //special trait
trait UIEvent extends Event //special trait

case class Results extends Event   //concrete case class
case class Query extends Event     //concrete case class

case class Running extends Status  //concrete case class
case class Finished extends Status //concrete case class

case class Update extends UIEvent  //concrete case class

我运行以下测试

  val events = List(Results, Query, Running, Finished, Update)
    events foreach {
      case Results => println("Got a Results")
      case Running => println("Got a Running")
      case s:Status => println("Got some StatusEvent")
      case ui:UIEvent => println("Got some UIEvent")
      case e: Event => println("Generic Event")
      case x => println("Didn't matched at all " + x)
    }
    println("############################")
    val STATUS = classOf[Status]
    val EVENT = classOf[Event]
    val UIEVENT = classOf[UIEvent]
    val RESULTS = classOf[Results]
    val eventsClass = events map (_.getClass)
    eventsClass foreach {
      case RESULTS => println("Got a Results")
      case STATUS => println("Got some StatusEvent")
      case UIEVENT =>  println("Got some UIEvent")
      case EVENT => println("Generic Event")
      case x => println("Didn't matched at all " + x)
    }

,导致以下输出

Got a Results
Didn't match at all Query
Got a Running
Didn't match at all Finished
Didn't match at all Update
############################
Didn't match at all class de.mukis.scala.test.main.Results$
Didn't match at all class de.mukis.scala.test.main.Query$
Didn't match at all class de.mukis.scala.test.main.Running$
Didn't match at all class de.mukis.scala.test.main.Finished$
Didn't match at all class de.mukis.scala.test.main.Update$

为什么我不能在案例类和特征上或仅在类上进行模式匹配?

I want to match on some case classes. If I don't know them, I want to match on a specified trait the classes have to extend. This looks like

trait Event  //root trait
trait Status extends Event  //special trait
trait UIEvent extends Event //special trait

case class Results extends Event   //concrete case class
case class Query extends Event     //concrete case class

case class Running extends Status  //concrete case class
case class Finished extends Status //concrete case class

case class Update extends UIEvent  //concrete case class

I run the following test

  val events = List(Results, Query, Running, Finished, Update)
    events foreach {
      case Results => println("Got a Results")
      case Running => println("Got a Running")
      case s:Status => println("Got some StatusEvent")
      case ui:UIEvent => println("Got some UIEvent")
      case e: Event => println("Generic Event")
      case x => println("Didn't matched at all " + x)
    }
    println("############################")
    val STATUS = classOf[Status]
    val EVENT = classOf[Event]
    val UIEVENT = classOf[UIEvent]
    val RESULTS = classOf[Results]
    val eventsClass = events map (_.getClass)
    eventsClass foreach {
      case RESULTS => println("Got a Results")
      case STATUS => println("Got some StatusEvent")
      case UIEVENT =>  println("Got some UIEvent")
      case EVENT => println("Generic Event")
      case x => println("Didn't matched at all " + x)
    }

which leads to the following output

Got a Results
Didn't match at all Query
Got a Running
Didn't match at all Finished
Didn't match at all Update
############################
Didn't match at all class de.mukis.scala.test.main.Results$
Didn't match at all class de.mukis.scala.test.main.Query$
Didn't match at all class de.mukis.scala.test.main.Running$
Didn't match at all class de.mukis.scala.test.main.Finished$
Didn't match at all class de.mukis.scala.test.main.Update$

Why can't I pattern match on case class and traits or just only on the class?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

守护在此方 2024-12-14 08:10:26

问题是您引用的是案例类的伴随对象,而不是它们的特定实例。因此,REPL 应该已经向您提供了弃用警告。

解决方案是添加一些括号:

sealed abstract trait Event
sealed abstract trait Status extends Event
sealed abstract trait UIEvent extends Event

case class Results() extends Event
case class Query() extends Event

case class Running() extends Status
case class Finished() extends Status

case class Update() extends UIEvent

and

val events = List(Results(), Query(), Running(), Finished(), Update())
events foreach {
  case Results() => println("Got a Results")
  case Running() => println("Got a Running")
  case s:Status => println("Got some StatusEvent")
  case ui:UIEvent => println("Got some UIEvent")
  case e: Event => println("Generic Event")
  case x => println("Didn't match at all " + x)
}

或,正如 didierd 建议的那样,使用 case 对象

sealed abstract trait Event
sealed abstract trait Status extends Event
sealed abstract trait UIEvent extends Event

case object Results extends Event
case object Query extends Event

case object Running extends Status
case object Finished extends Status

case object Update extends UIEvent

val events = List(Results, Query, Running, Finished, Update)
events foreach {
  case Results => println("Got a Results")
  case Running => println("Got a Running")
  case s:Status => println("Got some StatusEvent")
  case ui:UIEvent => println("Got some UIEvent")
  case e: Event => println("Generic Event")
  case x => println("Didn't match at all " + x)
}

The problem is that you're referring to the companion objects for your case classes, not specific instances of them. The REPL should already have supplied you with deprecation warnings due to this.

The solution is to add a few parentheses:

sealed abstract trait Event
sealed abstract trait Status extends Event
sealed abstract trait UIEvent extends Event

case class Results() extends Event
case class Query() extends Event

case class Running() extends Status
case class Finished() extends Status

case class Update() extends UIEvent

and

val events = List(Results(), Query(), Running(), Finished(), Update())
events foreach {
  case Results() => println("Got a Results")
  case Running() => println("Got a Running")
  case s:Status => println("Got some StatusEvent")
  case ui:UIEvent => println("Got some UIEvent")
  case e: Event => println("Generic Event")
  case x => println("Didn't match at all " + x)
}

or, as didierd suggests, use case objects

sealed abstract trait Event
sealed abstract trait Status extends Event
sealed abstract trait UIEvent extends Event

case object Results extends Event
case object Query extends Event

case object Running extends Status
case object Finished extends Status

case object Update extends UIEvent

and

val events = List(Results, Query, Running, Finished, Update)
events foreach {
  case Results => println("Got a Results")
  case Running => println("Got a Running")
  case s:Status => println("Got some StatusEvent")
  case ui:UIEvent => println("Got some UIEvent")
  case e: Event => println("Generic Event")
  case x => println("Didn't match at all " + x)
}
尽揽少女心 2024-12-14 08:10:26

您的问题是没有括号的案例类(现已弃用)。案例类意味着伴随对象的创建。当您在列表和模式匹配中编写不带括号的结果时,它表示伴生对象。

您可以尝试

define sortOut(x: Any) = x match {
  case Results => "companion object"
  case Results() => "instance"
}

sortOut(Results) // returns companion object
sortout(Results()) // returns instance

这解释了第二部分中的行为。由于 Results 是伴随对象,Results.getClass() 不是实例的类 classOf[Results],而是伴随对象的(合成)类,Results$< /code>

如果 case 类 没有参数,大多数时候这意味着各个实例无法相互区分,而您应该使用 case 对象。否则,请加上括号。

Your problem is with case class without parantheses (which are now deprecated). A case class implies the creation of a companion object. When you write Results without parantheses, both in your list, and in the pattern matching, it means the companion object.

You may try

define sortOut(x: Any) = x match {
  case Results => "companion object"
  case Results() => "instance"
}

sortOut(Results) // returns companion object
sortout(Results()) // returns instance

This explains the behavior in the second part. As Results is the companion object, Results.getClass() is not classOf[Results], which is the class of instance, but the (synthetic) class of the companion object, Results$

If a case class has no parameters, most of the time it means that various instances cannot be distinguished from each other, and you should rather use a case object. Otherwise, put the parantheses.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文