2017-04-27 48 views
2

比方說,我有以下特點Scala的抽象數據類型 - 是有沒有辦法從字符串中的一種通用的方式反序列化

trait Named { 
    def name: String 
} 

和下面的代數數據類型

sealed trait Animal extends Named 

case object Dog extends Animal { 
    override val name: String = "dog man" 
} 

case object Cat extends Animal { 
    override val name: String = "cat man" 
} 

case object Owl extends Animal { 
    override val name: String = "I am an owl left in the dark" 
} 

現在,我可以使用以下方法將字符串實例反序列化到我的Animal ADT中。

object Animal { 

    def apply(name: String): Animal = name match { 
    case Dog.name => Dog 
    case Cat.name => Cat 
    } 
} 

@oxbow_lakes提到在他的answer的結尾:

無法從持久價值容易實例。這也是如此,除了在大量列舉(例如所有貨幣)的情況下, , 這並不會帶來巨大的開銷。

我發現,當你添加一個新值時,它需要被顯式添加到反序列化代碼中,因爲容易出錯(我認爲編譯器會警告我一個詳盡的匹配,但要採取看上面的Owlapply方法 - 沒有發出警告......)

有沒有更好的方法? (如果不符合標準的Scala工具包,第三方嗎?)

+0

待辦事項我,回答我的問題。基於兩個帖子找到解決方案: http://stackoverflow.com/questions/25838411/cant-prove-that-singleton-types-are-singleton-types-while-generating-type-class 和 http:///stackoverflow.com/questions/43650265/implicit-arguments-how-to-encode-in-function-signature 總結爲:http://stackoverflow.com/a/43658710/101715 – Yaneeve

回答

3

有一兩件事你可以嘗試是使用反射來獲得該組的擴展Animal類型,然後使用該使用name查找對象創建一個Map[String,Animal]值,然後在Animal.apply函數中使用該地圖。

有關獲取Animal子類的更多信息,請參閱this question

+0

它會工作,但我寧願如果可能的話,一種沒有反思的方式 – Yaneeve

+0

只是出於好奇,爲什麼你更願意避免反思?您只需要使用一次即可將'String'設置爲'Animal'地圖,所以它不會影響性能,並且不會錯過任何'Animal'子類。 –

+0

很明顯,您的評估在正確性和效率方面是正確的。我認爲使用編譯時解決方案讓我感覺更好的原因在於,在我看來,應該有辦法做到這一點。 「密封特徵」告訴編譯器不會有任何運行時擴展,這意味着所有已知的直接子類型都是事先已知的。我認爲這個知識應該是可以利用的。我不知道該怎麼做,所以我發佈了這個問題。我想知道是否我希望可以用不成形的宏或宏來完成。恕我直言,一般來說,編譯時可以做些什麼 – Yaneeve

4

已經enumeratum庫解決了這個問題: https://github.com/lloydmeta/enumeratum

你的代碼可以這樣寫:

import enumeratum._ 
import enumeratum.EnumEntry.Lowercase 

sealed trait Animal extends EnumEntry with Lowercase 
object Animal extends Enum[Animal] { 
    val values = findValues 

    case object Dog extends Animal 
    case object Cat extends Animal 
    case object Owl extends Animal 
} 

val dogName = Animal.Dog.entryName 
val dog = Animal.withNameInsensitive(dogName) 
相關問題