2017-07-20 4 views
0

Es gibt bereits Informationen darüber, was ich tun möchte, aber ich konnte es noch nicht herausfinden. Ich möchte ein Element eines Typs als Kontext gebunden, so etwas wie dies passiert instanziiert:Scala 2.12, Instanziat Typ Parameter?

case class Person(name: String) 
case class Dog(name: String) 

abstract case class Message[T](result: Map[String, T]) 

// using Person as a type here 
case class PersonMessage(val result: Map[String, Person]) extends Message[Person](result) 

// using Dog as a type here 
case class DogMessage(val result: Map[String, Dog]) extends Message[Dog](result) 

ich sicherlich diese Objekte instanziieren:

val pm: PersonMessage = PersonMessage(Map("joe" -> Person("joe"))) 
val dm: DogMessage = DogMessage(Map("blacky" -> Dog("blacky"))) 

aber konnte ich tun dies in einer generischen Funktion ?

// should return a PersonMessage or a DogMessage 
def myfunction[T, U <: Message[T]](customName: String): U = { 
    U(Map(customName -> T(customName))) 
} 

val p: PersonMessage = myFunction[Person, PersonMessage]("joe") 
val d: DogMessage = myFunction[Dog, DogMessage]("blacky") 

Diese Syntax funktioniert nicht, aber gibt es andere Möglichkeiten, dies zu erreichen? Danke für jeden Hinweis.

Antwort

1

Das Problem ist, dass durch die Definition des Typs T oder U <: Message[T] Sie keine Garantien haben, welche Art von Argumenten die Konstruktoren nehmen. Warum konnte jemand nicht mit T auf einen Typ ohne einen Konstruktor mit einem String-Argument setzen? Stattdessen können Sie Konstruktoren mit den entsprechenden Typen explizit übergeben. Hier ist, wie ich damit umgehen würde:

def myFunction[T, U <: Message[T]](customName: String, mkT: String => T, mkU: Map[String, T] => U): U = { 
    mkU(Map(customName -> mkT(customName))) 
} 

val p: PersonMessage = myFunction("joe", Person, PersonMessage) 
val d: DogMessage = myFunction("blacky", Dog, DogMessage) 
+0

Danke Joe! Die einzige andere Sache, die ich tun musste, war, die Basisklasse zu einer Klasse (und nicht zu einer Fallklasse) zu machen, da diese nicht erweiterbar ist. – ticofab

Verwandte Themen