TL; DR: Es scheint, dass Typ Parameter des Typs Aliase (z. B. type T[X<:Serializable]
) ihre Einschränkungen nicht erzwingen, wenn als Variablen, Parameter und vielleicht andere Fälle verwiesen. Fallklassen erzwingen jedoch die Grenzen für ihre Parameter korrekt.Typ Alias-Parameter Grenzen nicht in allen Fällen erzwungen
Betrachten Sie einen Typalias, der eine Untermenge des generischen Typs darstellt. Zum Beispiel lassen Sie uns sagen, dass ich einen Typen für Listen von Serializable
Dingen will:
scala> type SerializableList[T <: Serializable] = List[T]
defined type alias SerializableList
Jetzt sagen, dass ich eine Fall-Klasse mit einem Parameter dieser Dinge will:
scala> case class NetworkDataCC(things: SerializableList[_])
<console>:9: error: type arguments [_$1] do not conform to type SerializableList's type parameter bounds [T <: Serializable]
case class NetworkDataCC(things: SerializableList[_])
Nun, das doesn‘ t arbeiten. Scala (annoyingly) trägt nicht die Parametergrenzen mit der Art, aber es ist einfach zu beheben:
scala> case class NetworkDataCC(things: SerializableList[_ <: Serializable])
defined class NetworkDataCC
In Ordnung. Sieht gut aus. Nun, was ist, wenn ich nur eine reguläre Klasse mit diesen Dingen möchte, aber ich vergesse wieder, die Typgrenzen explizit zu deklarieren. Ich erwarte einen Fehler:
scala> class NetworkData(val things: SerializableList[_])
defined class NetworkData
Oh, warte. Kein Fehler ... huh.
Also, jetzt kann ich das tun?
scala> new NetworkData(List(1))
res3: NetworkData = [email protected]
Nun, das scheint ziemlich kaputt. Der Fall Klasse, funktioniert natürlich (weil die Beschränkungen erklärt wurden):
scala> NetworkDataCC(List(1))
<console>:11: error: type mismatch;
found : Int(1)
required: Serializable
NetworkDataCC(List(1))
In meinem Projekt habe ich den Einsatz von Reflexion mache einige Metadaten über meine Klassen zu erzeugen. Die Metadaten für die Nicht-Fall-Klasse zeigen einen Mangel an Grenzen auf things
:
scala> classOf[NetworkData].getDeclaredFields()(0).getGenericType
res0: java.lang.reflect.Type = scala.collection.immutable.List<?>
Während die Fallklasse ist richtig:
scala> classOf[NetworkDataCC].getDeclaredFields()(0).getGenericType
res1: java.lang.reflect.Type = scala.collection.immutable.List<? extends scala.Serializable>
ich in der scala alle Fehler finden nicht in der Lage war, Compiler-Bug-Tracker dafür. Missverstehe ich, wie diese Grenzen verwendet werden sollten?
Interessante Frage. Ich vermute, dass der Compiler die von der Fallklasse erzeugte 'unapply'-Methode erstickt. Ich frage mich, warum die nicht-Fall-Klasse kompiliert. Aber das Problem scheint sich zu manifestieren, auch wenn wir keine neue Klasse deklarieren. Der Compiler akzeptiert happly "val y: SerializableList [_] = List (1)", was bereits ein ungültiger Ausdruck sein sollte. Vielleicht verursacht der Typ-Alias das Problem? –
Addendum (nicht-Fall-Klasse) zu meinem vorherigen Kommentar: Die Funktion 'def unapply (Wert: NetworkDataCC): Option [SerializableList [_]] = Einige (value.things)' kompiliert nicht, Drucken der Fehler: 'Typ Argumente [_ $ 1] stimmen nicht mit Typ-Parametergrenzen des Types SerializableList [T <: Serializable] 'überein. Der Compiler akzeptiert jedoch 'def unapply (value: NetworkDataCC): Option [SerializableList [_]] = Einige (value.things.asInstanceOf [SerializableList [Serializable]])', die auch mit 'NetworkDataCC (List (1)) 'übereinstimmen Zur Laufzeit gibt 'List (1)' zurück. –
Ich bin sehr interessiert an diesem. Ich habe eine Prämie angefangen, hoffentlich kann jemand antworten. –