2016-02-03 26 views
0

我在看這個代碼類型的類在scala中繼承`.apply`嗎?

def loginForm = Form(mapping("username" -> text, "password" -> text) 
    (LoginRequest.apply)(LoginRequest.unapply)) 

case class LoginRequest(username:String, password:String) 

這裏是表格的源代碼中Play

def mapping[R, A1, A2](a1: (String, Mapping[A1]), 
         a2: (String, Mapping[A2])) 
         (apply: Function2[A1, A2, R]) 
         (unapply: Function1[R, Option[(A1, A2)]]): 
    Mapping[R] = { 
     new ObjectMapping2(apply, unapply, a1, a2) 
    } 

我試圖找出

LoginRequest.apply 

實際上意味着什麼

ObjectMapping2(LoginRequest.apply, LoginRequest.unapply, "username" -> text, "password" -> text) 

+0

類型類在哪裏,它與類型類型有什麼關係? –

回答

2

LoginRequestcase class,因此包含的方法applyunapply,由編譯器自動插入。玩需要他們知道如何從映射中構建和解構你的域對象。如果你有一些自定義的代碼,你需要一個自定義的應用/不應用,但是因爲你正在使用一個case類(這是正確的做法),你可以簡單地傳遞它的應用和不應用函數。

因此,要回答你的第一個問題,LoginRequest.apply是對每個案例類都可用的應用函數的調用。

要回答你的第二個問題,

ObjectMapping2(LoginRequest.apply, LoginRequest.unapply, "username" -> text, "password" -> text)` 

是說,一個新的LoginRequest將從「用戶名」和「密碼」字符串由他們傳遞給LoginRequest.apply這是您的LoginRequest情況下類的構造函數來創建。它還表示解構LoginRequest是使用LoginRequest.unapply完成的,它將返回Option[(String, String)](每個參數的一個字符串,在您的用戶名和密碼中)。

編輯:

我的意見而遭警告,要更精確。因此,在定義一個案例類時,編譯器會在其伴隨對象中自動生成apply()unapply()。您始終可以將這些方法包含在您定義的任何類的任何伴隨對象中。在這種情況下,編譯器會爲你做。方法apply()是「特殊的」,因爲它允許使用特殊的語法糖:而不是調用Something.apply(),它也可以簡單地調用Something()

請注意,apply()unapply()不會被覆蓋或實施;你(或者在這種情況下是編譯器)只是簡單地從頭開始定義它們,就像其他自定義方法一樣。但這是Scala編譯器中的「技巧」,它允許語法糖。因此,如果您在MyClass的隨播對象中定義了apply()方法,那麼您當然可以按照通常的方式調用它,如MyClass.apply(whatever),但也可以使用MyClass(whatever)(這是一個絕妙的部分)。

即使您有時不知道它,您也可以一直使用它 - 例如,List(1, 2, 3)實際上已被編譯器清除爲List.apply(1, 2, 3)。這個技巧使我們程序員可以編寫更漂亮,更易讀的代碼(List.apply()很醜,是不是?)

無關的這個特定的問題,但讓我提太 - 編譯器也將添加一些其他的方法case類:copytoStringequalshashCode。與applyunapply不同,這些方法將被添加到(因此,不需要調用伴隨對象,如applyunapply,那些需要在case類的實例上調用這些方法)。

+0

很好的答案,但如果我沒有弄錯,'apply'方法被添加到case類中,因爲聲明case類將自動爲新創建的類創建伴隨對象,並且伴隨對象實現'apply'方法。我認爲這是值得添加到答案,一個完整的解釋。 – Dani

+0

是的,編譯器會將apply()的實現添加到case類的伴侶對象。更新答案更加精確。 – slouc