2016-12-09 108 views
1

讓我們說我有一個通用的案例類:斯卡拉:模式匹配「具體」的情況下

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" 
     //MetaData(MetaData(_))=>"metaMeta1" //a 
     case _:MetaData[MetaData[_]]=>"metaMeta2" //b 
     //case MetaData(data:Data)=>"meta"+ getDataTypeName(data) //c 
     //MetaData(TextData(_))=>"metaMeta1" //d 
     case MetaData(_)=>"meta" 
    } 
} 

我希望能夠看到,如果我的數據是元 - 元數據,元的TextData等 a行給我一個錯誤,他說:

構造不能實例化爲預期的類型;實測值: 研究所$ A $ A.MetaData [d]要求:A $ A115.this.Data情況 元數據(metadata(_))=> 「metaMeta1」

我寧願有類似的東西線a。或者像c這樣的東西也不錯。我也試過b。這一個產生一些警告:

非可變類型參數甲$ A115.this.MetaData []在 型圖案A $ A115.this.MetaData [A $ A115.this.MetaData []]是 選中,因爲它是由擦除 情況下消除:元數據[元數據[] => 「metaMeta」 ^

我得到這樣的警告兩個MetaData[_]s。我的理解是,在與我的測試結果一致的類型擦除之後,所述模式減少到_。

因此,我想知道是否有針對MetaMetaDataMetaTextData

或者,他們不應該被用來MetaMetaMetaData使用密封類的方式我的設計相匹配的一種方式?你會建議什麼替代設計?

+0

我認爲對元數據的比賽,然後再匹配以檢查內部類是不是你理想的解決方案? '''data match {case Metadata(x)=> x match {...}} – pedrorijo91

+0

我想我也會很高興。事實上,我確實嘗試了類似的做法(c行),但無法獲得正確的語法。 – ShS

回答

3

我對MetaData()定義進行了更改以使其工作。在REPL

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 
+0

哦,我明白了。這讓我想到:在編譯器如何看待它之前,先前的定義和這個定義之間有沒有真正的區別? – ShS

+0

好吧,顯然編譯器會以不同的方式看到它們,因爲它不會在原始定義下編譯。它會對你的代碼產生影響嗎?可能不會。 – jwvh

+0

我想不同的是,在舊的定義中,數據實際上與作爲子類型的對象相連接,而在新的格式中,它僅僅是基類的一個實例。但這真的很重要嗎?不是真的。 – ShS

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

測試:

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

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

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

酷!但斯卡拉2.11.7不喜歡這樣。 :/ – ShS

+0

真的嗎?什麼是錯誤? – pedrorijo91