2015-03-28 9 views
6

Ich habe Codierung mit Akka/Scala vor kurzem damit begonnen, und ich habe in folgendem Problem führen:Mit mapTo mit Futures in Akka/Scala

Mit einer impliziten Umwandlung in Umfang, wie zum Beispiel:

implicit def convertTypeAtoTypeX(a: TypeA): TypeX = 
    TypeX() // just some kinda conversion 

Dies funktioniert:

returnsAFuture.mapTo[TypeX].map { x => ... } 

Aber dies nicht:

returnsAFuture.mapTo[TypeX].onComplete { ... } 

Letzteres schlägt mit einer Typumwandlungsausnahme fehl. (d. h. TypA kann nicht in TypeX umgewandelt werden)

Sehr verwirrt. Warum? Ich vermute, dass es etwas mit Versuchen zu tun hat, aber ich weiß nicht genug über entweder bei jeder Art von Antwort zu erraten :(

Dank

Antwort

7

Von doc:

def mapTo[S](implicit tag: ClassTag[S]): Future[S] 
    Creates a new Future[S] which is completed with this Future's result if that conforms to S's erased type or a ClassCastException otherwise. 

Diese Funktion kann nicht verwendet werden, um zwischen Objekten zu konvertieren, die sich in einer Vererbungsbeziehung befinden.Es erwartet keinen impliziten Beweis für die Konvertierung von [T] nach [S]

Diese Funktion wird zB in Akka gebraucht, wo man einen Schauspieler fragt und als Antwort Fut erhält ure [Irgendwelche]. Aber du weißt, dass ein Schauspieler dir String zurückgibt, damit du sicher schreiben kannst actor.ask(...).mapTo[String] und das wird funktionieren, weil Any zu allem gecastet werden kann. Implizite Konvertierungen werden hier nicht verwendet.

Jetzt sagen Sie, dass Ihr erstes Beispiel funktioniert. Aber diese Zeile wird nicht einmal berechnet, da Sie nie nach einem Ergebnis fragen. Um zu visualisieren, scala Compiler sagt: naja, Sie tun nur eine Karte (Wechsel von Typ X zu Typ Y) ein Ergebnis dieser Zukunft, aber nie tatsächlich verwenden, warum also stören Sie sogar ausführen, wenn Sie sich nicht kümmern?

Wenn Sie onComplete nach Ihrer Map in der ersten Zeile hinzugefügt haben, sehen Sie dieselbe ClassCastException.

Dies ist wahrscheinlich jetzt, was Sie wollen, aber das ist interessant:

returnsAFuture.map { x => x.fieldOnlyInTypeX } 

wenn Sie „x“, als ob es vom Typ war TypeX alles gut funktionieren wird. Der Scala-Compiler wendet eine implizite Konvertierung in "x" an, um ihn in TypeX zu konvertieren. Dies ist wahrscheinlich nicht das, was Sie wollen, weil "x" immer noch vom Typ TypeA ist und implizit für jede Verwendung in map konvertiert wird.

~ Krzysiek

+0

Jede Idee, was ist die Leistung von mapTo? – EugeneMi