2016-01-18 3 views
2

Étant donné ce code:Scala type structural avec la méthode où seuls quelques params sont connus

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) 
} 

Comment puis-je mettre en œuvre « type HasCopyMethodWithId » de sorte que ce code compile et ne manque pas à l'exécution?

J'ai essayé:

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

Je pense que vous ne pouvez pas, ces méthodes de copie sont différentes. Vous devrez créer une autre méthode comme 'copyId' qui utiliserait copy. –

+0

Le type réel (pas un type structurel général) peut-il être détecté via des macros? – eirirlar

Répondre

4

La méthode copy synthétique fourni par les classes de cas est une seule méthode avec tous les arguments de cette catégorie de cas, pas une personne en surcharge un pour id, firstName etc. Par conséquent le type structurel ne correspond pas.

Vous pouvez ajouter une méthode auxiliaire:

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) 

Mais certainement mieux est de fournir un type statique:

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

Vous avez une erreur ici 'type HasCopyMethodWithId = {def copyID' –

+0

@ Łukasz merci, corrigé –