2016-01-18 41 views
2

鑑於此代碼:斯卡拉與方法的構造類型,其中只有一些PARAMS已知

object Testy extends App { 

    case class Person(
        id: Option[Long], 
        firstName: String, 
        lastName: String, 
        address: Address) 

    case class Address(id: Option[Long], 
        name: String, 
        number: Int) 

    val personOrAddress:AnyRef= Person(Some(1L), "first", "last", Address(Some(1L), "street", 1)) 
    type HasCopyMethodWithId = _ 
    val newId = Some(123L) 
    personOrAddress.asInstanceOf[HasCopyMethodWithId].copy(id = newId) 
} 

我怎樣才能實現「類型HasCopyMethodWithId」,讓這個代碼編譯和運行時不會失敗?

我試着:

type HasCopyMethodWithId = {def copy(id: Option[Long]): AnyRef} 
+1

我認爲你不能,這些複製方法是不同的。您將不得不創建另一種方法,如使用副本的'copyId'。 –

+0

是否可以通過宏檢測實際類型(不是一般結構類型)? – eirirlar

回答

4

由case類所提供的合成方法copy是一個單一方法,該情況下的類的所有參數,而不是一個單獨的重載一個用於idfirstName等,因此結構類型不匹配。

您可以添加一個輔助方法:

case class Person(id: Option[Long], 
        firstName: String, 
        lastName: String, 
        address: Address) { 

    def copyId(newId: Option[Long]): Person = copy(id = newId) 
} 

case class Address(id: Option[Long], 
        name: String, 
        number: Int) { 
    def copyId(newId: Option[Long]): Address = copy(id = newId) 
} 

val personOrAddress: Any = 
    Person(Some(1L), "first", "last", Address(Some(1L), "street", 1)) 

type HasCopyMethodWithId = { def copyId(id: Option[Long]): Any } 
val newId = Some(123L) 
personOrAddress.asInstanceOf[HasCopyMethodWithId].copyId(id = newId) 

但隨後幾乎肯定更好的是提供一個靜態類型:

trait CopyWithId { 
    type Repr 
    def copyId(id: Option[Long]): Repr 
} 

case class Person(id: Option[Long], 
        firstName: String, 
        lastName: String, 
        address: Address) extends CopyWithId { 

    type Repr = Person 
    def copyId(newId: Option[Long]): Person = copy(id = newId) 
} 

case class Address(id: Option[Long], 
        name: String, 
        number: Int) extends CopyWithId { 

    type Repr = Address 
    def copyId(newId: Option[Long]): Address = copy(id = newId) 
} 

val personOrAddress: CopyWithId = 
    Person(Some(1L), "first", "last", Address(Some(1L), "street", 1)) 

val newId = Some(123L) 
personOrAddress.copyId(id = newId) 
+0

這裏有一個錯字'HasCopyMethodWithId = {def copyID' –

+0

@Łukaszthanks,corrected –