2014-10-27 115 views
1

假設我們的東西的模型,表示爲case class,因爲這樣獲取字段名稱和類型從案例類(含選項)

case class User(firstName:String,lastName:String,age:Int,planet:Option[Planet]) 

sealed abstract class Planet 
case object Earth extends Planet 
case object Mars extends Planet 
case object Venus extends Planet 

本質上,或者通過使用反射,或宏的,要能夠獲取用戶案例類的字段名稱以及字段表示的類型。這也包括Option,即在所提供的例子,需要能夠在Option[Planet],只是一個Planet

在scala'ish僞代碼,東西區分這樣

val someMap = createTypedMap[User] // Assume createTypedMap is some function which returns map of Strings to Types 
someMap.foreach{case(fieldName,someType) { 
    val statement = someType match { 
     case String => s"$fieldName happened to be a string" 
     case Int => s"$fieldName happened to be an integer" 
     case Planet => s"$fieldName happened to be a planet" 
     case Option[Planet] => s"$fieldName happened to be an optional planet" 
     case _ => s"unknown type for $fieldName" 

    } 
    println(statement) 

} 

我現在知道你不能做像case Option[Planet]這樣的東西,因爲它被Scala的擦除擦除,但是即使在使用TypeTags時,我也無法編寫代碼來完成我正在嘗試做的事情,並可能處理其他類型(如Either[SomeError,String])。

目前我們使用的是最新版本的Scala(2.11.2),所以任何使用TypeTagsClassTags或宏的解決方案都會綽綽有餘。

+0

英里薩賓的答案http://stackoverflow.com/questions/23192760/safely-copying-fields-between-case-classes-of-different-types有幫助嗎? – 2014-12-28 04:54:46

回答

-1

這是一個遠射,但也許Shapeless可以幫助你。

+0

有沒有什麼特殊的Shapeless,你可以指向哪些可以讓你做到這一點? – mdedetrich 2014-10-27 23:34:06

+0

無形有將元組轉換爲HList的方法,期望將案例類轉換爲HList是合理的。 HLists是完全鍵入的,所以你可以對它們進行匹配。但正如我寫的,它是一個遠射:) – 2014-10-28 10:55:49

+0

RúnarÓli的另一個提示(不知道這是如何工作的):使用模式匹配器將字符串解析爲Scala宏中的類型。 '(s:String)=> {val q「type T = $ t」= c.parse(s「type T = $ s」); t}' – 2014-10-28 10:58:50

1

選項是一個類型參數化類型(選項[T])。在運行時,除非已經將代碼構造爲使用type tags,否則由於類型擦除(對於所有類型參數化類型都是如此),您無意區分Option [String]和Option [Int]。儘管如此,您可以區分Option [*]和Planet。請記住第一個問題。

通過反思,讓一個班級內的所有「事物」變得容易。例如,假設你只需要獲取者(你可以放置其他類型的過濾器,其中有很多過濾器,並且當繼承是過程的一部分時,並不是所有的行爲都如預期的那樣,所以你需要嘗試一下):

import reflect.runtime.{universe=>ru} 
val fieldSymbols = ru.typeOf[User].members.collect{ 
    case m: ru.MethodSymbol if m.isGetter => m 
} 

你有,如果你正在呼籲實例,而不是類的代碼另一種選擇,是要經過每一個方法,調用方法和結果分配給一個變量,然後測試類型的變量。這假定你只調用不改變實例狀態的方法。

您有很多選擇,有時間爲您找到最適合您需要的選項。

+0

看起來最好的選擇是使用宏或者某個實現了宏的庫) 由於正在指出的類型擦除問題,試圖通過檢查getters/setters來檢測Option是非常不理想的(它也可以輕鬆地在Scala發佈) – mdedetrich 2014-10-27 23:39:51