Scala:模式匹配"具体"的通用案例类。例

时间:2016-12-09 23:08:20

标签: scala types pattern-matching

让我说我有:

sealed trait Data
final case class TextData()  extends Data
final case class ImageData() extends Data
final case class MetaData[D <: Data](data: D) extends Data

我想模式匹配Data对象。我已定义:

def getDataTypeName(data: Data): String ={
    data match {
        case TextData()=>"text"
        case ImageData()=>"image"
        //MetaData(MetaData(_))=>"metaMeta1"  //a
        case _:MetaData[MetaData[_]]=>"metaMeta2"  //b
        //case MetaData(data:Data)=>"meta"+ getDataTypeName(data) //c
        //MetaData(TextData(_))=>"metaMeta1"  //d
        case MetaData(_)=>"meta"
    }
}

我希望能够看到我的数据是元元数据,元文本数据等。 第a行给我一个错误,说:

  

构造函数无法实例化为期望的类型;发现:   inst $ A $ A.MetaData [D]必需:A $ A115.this.Data案例   元数据(metadata(_))=&GT;&#34; metaMeta1&#34;

我更喜欢有类似行a的东西。或者像c这样的东西也会很好。

我也试过了行b。这个会产生一些警告:

  

非变量类型参数A $ A115.this.MetaData [] in   类型模式A $ A115.this.MetaData [A $ A115.this.MetaData []]是   因为擦除而被删除,所以不加以控制               case :MetaData [MetaData []] =&gt;&#34; metaMeta&#34;                      ^

我收到了MetaData[_]s的警告。我的理解是,在类型擦除后,所述模式减少到_,这与我的测试结果一致。

因此,我想知道是否有一种方法可以与MetaMetaDataMetaTextDataMetaMetaMetaData等进行匹配。

或者,我的设计是否以不应该使用的方式使用密封类?你会建议什么样的替代设计?

2 个答案:

答案 0 :(得分:3)

我对MetaData()定义进行了更改,以使其发挥作用。

sealed trait Data
final case class TextData()  extends Data
final case class ImageData() extends Data
final case class MetaData(data: Data) extends Data

def printType(data: Data): String = data match {
  case TextData()=>"text"
  case ImageData()=>"image"
  case MetaData(d)=>"meta:" + printType(d)
}

val md = MetaData( MetaData(TextData()) )
printType(md)  // res0: String = meta:meta:text

答案 1 :(得分:0)

  sealed trait Data
  final case class TextData()  extends Data
  final case class ImageData() extends Data
  final case class MetaData[D <: Data](data: D) extends Data

def getDataTypeName(data: Data): String ={
    data match {
      case TextData()=>"text"
      case ImageData()=>"image"
      case MetaData(MetaData(_))=> "metaMeta1" 
      case MetaData(TextData())=> "textMeta1"  
      case MetaData(ImageData())=> "imgMeta1"  
    }
  }

在REPL上进行测试:

scala> getDataTypeName(TextData())
res1: String = text

scala> getDataTypeName(MetaData(TextData()))
res2: String = textMeta1

scala> getDataTypeName(MetaData(MetaData(TextData())))
res3: String = metaMeta1