2016-01-18 11 views
2

Учитывая этот код:Scala структурного типа с методом, где только некоторый 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

Синтетический copy метод, предоставляемый случае классов один единый метод со всеми аргументами этого дела класса, а не физическое лицо перегружен один за id, firstName и т.д. Поэтому структурный тип не соответствует.

Можно добавить вспомогательный метод:

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

У вас есть опечатка здесь 'type HasCopyMethodWithId = {def copyID' –

+0

@ Łukasz спасибо, исправлено –