2012-01-05 133 views
2

在Groovy一個可以這樣做:斯卡拉案例類地圖擴展

class Foo { 
    Integer a,b 
} 
Map map = [a:1,b:2] 
def foo = new Foo(map) // map expanded, object created 

據我所知,Scala是不是在這個詞的,Groovy的任何意義,但如果在這種情況下地圖擴展支持想知道

簡單地說,我嘗試與失敗:

case class Foo(a:Int, b:Int) 
val map = Map("a"-> 1, "b"-> 2) 
Foo(map: _*) // no dice, always applied to first property 

一個相關thread,顯示的問題可能的解決方案。

現在,從我已經能夠挖掘出來的情況來看,至少從Scala 2.9.1開始,關於案例類的反思基本上是沒有用的。那麼淨效果似乎是人們被迫進入某種形式的手工對象創建,這在賦予Scala的力量的情況下有點諷刺。

我應該提一下,用例涉及servlet請求參數映射。具體來說,使用Lift,Play,Spray,Scalatra等,我想採用清理過的params圖(通過路由層過濾),並將其綁定到目標案例類實例,無需手動創建對象,也不指定其類型。這需要「可靠的」反射,並像「str2Date」那樣處理類型轉換錯誤。

也許在2.10用新的反射庫,執行上面的就會是蛋糕。僅僅2個月就進入斯卡拉,所以只是抓表面;我沒有看到任何直截了當的方式來解決這個問題(對於經驗豐富的Scala開發人員,也許是可行的)

+2

這當然不是直截了當的。然而,我不明白這個問題提出的問題是否與你所關聯的另一個人沒有解決 - 你能否澄清你的問題和那個問題之間的區別? – 2012-01-05 18:29:47

+0

我在問具體的地圖擴展。在Groovy中,映射會自動應用於每個類屬性。我假設用Scala _ *符號表示可以以相同的方式將地圖元素應用於案例類。顯然不是這樣的。我也想提出反思,因爲另一個線索沒有提到這個問題。 AFAIK,沒有反射,就不會有運行時間從一種類型轉換到另一種類型(例如,從SQL結果集到Scala對象到JSON)。我會犧牲性能,只需要節省我重複鍵入已定義的類屬性 - 一旦足夠... – virtualeyes 2012-01-05 19:01:26

回答

5

好吧,好消息是Scala的產品接口,由所有案例類實現,實際上並沒有做到這一點難做。我是一個名爲Salat的Scala序列化庫的作者,它提供了一些使用醃製Scala簽名來獲取輸入字段信息的實用程序。

https://github.com/novus/salat - 檢查salat-util包中的一些實用程序。

其實,我認爲這是薩拉特應該做的 - 這是一個好主意。回覆:D.C.Sobral關於在編譯時不可能驗證params的觀點 - 實際上,這應該在運行時工作,就像反序列化任何其他沒有結構保證的東西,比如JSON或Mongo DBObject。此外,薩拉特有實用程序可以利用所提供的默認參數。

+0

嗯,不要停止那裏;-)除了地圖擴展案例類實例化,實現toJson方法處理任意複雜的對象(你可能已經這樣做了,即將放棄某些禮拜)。對於scala web開發來說,主要的難點似乎是從SQL結果集到case類對象和case類對象到/來自JSON的強制轉換。在動態語言中,這些是1行;在斯卡拉他們往往是尾巴搖擺狗事務。我比較喜歡編譯時確定性的運行時靈活性(急於編譯時間太早,但是懶惰運行時間是JIT ;-)) – virtualeyes 2012-01-05 21:59:46

+0

我在本地git倉庫中使用了lift-json的一些json代碼。它尚未發佈 - 與此同時,你實際上可以在DBObject上做一個toString,並且......可用的JSON。不是最快或最乾淨的方式,但它確實很方便。 – prasinous 2012-01-05 23:00:35

+0

我其實前幾天檢查過這個。僅適用於Salat NoSQL還是適用於RBDMS? Spray用戶提到他們使用MongoDB和Salat是多麼的高興(意味着他們不需要手動強制SQL結果集到scala case類實例)。無論如何,讓我知道如果薩拉特有SQL的腿。謝謝... – virtualeyes 2012-01-05 23:36:16

3

這是不可能的,因爲在編譯時不可能驗證所有參數都在該映射中傳遞。

+1

因此,對於基於靜態編譯的任何語言來說這是不可能的;在不知道一個對象的類型(TBD運行時間參數映射)的情況下,已知對象(要構建的案例類)的類型不能匹配。動態和靜態語言之間的分界線。值得慶幸的是@prasinous表明,運行時解決方案是可能的,甚至可能在地圖擴展時(他似乎在這麼做)。 – virtualeyes 2012-01-05 21:29:20