2012-04-05 2 views
3

Hallo dort Stack-Überlauf,def fn [Zeichenfolge] scheint hier Scala/java.lang.String Kompatibilität

Ich hoffe, dass Sie mir helfen, mit meiner ersten Frage zu brechen :)

Also ich Ich habe ein Problem mit der Inferenz von Scala. Hier ist der Code:

object Problem { 

    def ok(fn: (String) => Unit) = fn("") 

    // type mismatch; found: java.lang.String("") required: String 
    def fail[String](fn: (String) => Unit) = fn("") 

} 

Welche Art von String erwartet Scala hier?

Beachten Sie, dass dies ein minimales Beispiel ist, um mein Problem zu erklären. Das ursprüngliche Problem tauchte auf, als ich versuchte, eine komplexere Schnittstelle zu implementieren (Play's Iteratee, um genau zu sein), also, nein, [String] ist keine Option. (Wenn jemand denkt, dass der tatsächliche Code helfen würde, werde ich es bereitstellen.)

Ich versuchte def fail[java.lang.String] ..., aber dann heißt es expected ], found ..

habe ich Scala String vs java.lang.String - type inference gelesen, die auf java.lang.String vs. scala.Predef.String eine gute Erklärung gibt, aber ich konnte immer noch nicht mit einer Lösung für mein spezielles Problem kommen.

Irgendwelche Ideen?

EDIT: So, hier ist der ursprüngliche Versuch, wie ich versuchte nur zu implementieren http://www.playframework.org/documentation/api/2.0/scala/play/api/libs/iteratee/Iteratee.html, dass ich String statt T schrieb. (Mit T kompiliert es, und es macht Sinn!) Mein Fehler; offensichtlich war ich ein bisschen von allen Typ Parameter überwältigt:

val stream = WS.url("url").get({ headers => 
    (new Iteratee[Array[Byte], String] { 
    def fold[T](done: (String, Input[Array[Byte]]) => Promise[T], 
       cont: (Input[Array[Byte]] => Iteratee[Array[Byte], String]) => Promise[T], 
       error: (String, Input[Array[Byte]]) => Promise[T]): Promise[T] = 
    { 
     done("something", Input.Empty) 
    } 
    }) 
}) 

Grüße, Hendrik

Antwort

9

Wenn Sie schreiben:

def fail[String](fn: (String) => Unit) = fn("") 

Der Typ-Parameter in eckigen Klammern String ist nur ein beliebiger Name Das wird in Ihrem Fall Scala oder Java String ausblenden. Es ist voll entspricht:

def fail[T](fn: (T) => Unit) = fn("") 

Wenn Sie den Typ String beschränken möchten, müssen Sie nur schreiben:

def fail(fn: (String) => Unit) = fn("") 

Und es wird für scala und Java-Strings arbeiten (da sie die sind gleich).

+0

Danke, ziemlich offensichtlich jetzt, dass Sie es sagen ...: | – Hendrik

+0

Diese Antwort ist korrekt, ich habe @ submonoid's gewählt, um mit der Signatur meiner Methode zu arbeiten, die ich nicht ändern kann. – Hendrik

+1

@Hendrik - Die Signatur macht keinen Sinn, soweit ich das beurteilen kann. Warum kannst du es nicht ändern? Was muss die Unterschrift sein? (Könnten Sie sich irren darüber, was es sein muss?) –

1

Dieses Problem hat nichts mit Java vs Scala Strings zu tun.

In der Zeile def fail[String](fn: (String) => Unit) = fn("") definieren Sie einen vollständig neuen Typ Parameter und benennen ihn String. Dies überschattet die allgemeine Definition.

Ein Typparameter wird benötigt, wenn Sie beabsichtigen, über den Typ zu abstrahieren. Sie tun dies nicht in dem fail Beispiel, und das sollte gelöscht werden.

Wenn Sie etwas überschreiben, die einen Typ-Parameter verwendet, dann sollten Sie dies auf class Ebene angeben:

class A extends B[String] 

auf den Code der Suche nach Iteratee, werde ich denke, Sie versuchen, fold zu implementieren mit seinen verschiedenen done, cont und error Funktionen. Fold hat nur einen Typparameter, der im Rückgabetyp verwendet wird, daher bin ich mir nicht sicher, woher das kommen kann. Die Parameter des Eingabetyps sind in der Klasse angegeben. Wenn Sie also Iteratee[String, Unit] erweitern, sollten diese angegeben werden.

+0

Ja, ich verstehe es jetzt - argh! Dispatching auf den Typ ist ein interessanter Ansatz. Vielen Dank! – Hendrik

+0

Das ist ein sehr guter Punkt, ich werde das entfernen. Entschuldigung, schrieb meine Antwort zu schnell. – Submonoid

+0

Schade, sah interessant aus; ( – Hendrik