简体   繁体   English

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

[英]Scala: Mix traits and case class in pattern match

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?为什么我不能对案例类和特征进行模式匹配,或者只能在类上进行模式匹配?

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.因此,REPL 应该已经为您提供了弃用警告。

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 object s或者,正如 didierd 所建议的,用case object

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

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.当您在列表和模式匹配中编写不带括号的 Results 时,它表示伴随对象。

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$由于 Results 是伴随对象, Results.getClass()不是 classOf[Results],它是实例的类,而是伴随对象的(合成)类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 .如果一个case class没有参数,大多数时候就意味着无法区分各个实例,而应该使用case object Otherwise, put the parantheses.否则,请放置括号。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM