首页 文章

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

提问于
浏览
13

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

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$

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

提前,Muki

2 回答

  • 23

    问题是您指的是案例类的伴随对象,而不是它们的特定实例 . 由于这个原因,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
    

    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 object s

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

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

    你可以试试

    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$

    如果 case class 没有参数,那么大多数情况下它意味着各种实例无法相互区分,您应该使用 case object . 否则,放上parantheses .

相关问题