2016-07-03 9 views
0

sagen, dass ich einen einzigen Parameter generische Methode machen:in welchen Fällen nicht scala richtig konvertieren String zu java.lang.String

trait MyTrait[T] { 
    def method():T 
} 

Und dann verlängern sie und parametrisieren. Dies:

class MyClass extends MyTrait[java.lang.String] { 
    def method() = "foo" 
} 

ist die gleiche wie folgt aus:

class MyClass extends MyTrait[String] { 
    def method() = "foo" 
} 

Wenn Sie jedoch ein Merkmal-Methode machen, die eine Lambda wie so parametrisiert:

trait MyTrait { 
    def apply[T](input:()=>T):T 
} 

Dann bist du nicht so glücklich. Dies:

class MyClass extends MyTrait { 
    def apply(input:()=>java.lang.String) = "foo" 
} 

Wird dazu führen:

Error:(25, 45) type mismatch; 
found : java.lang.String("foo") 
required: String 
     def apply[String](input:()=>String) = "foo" 
            ^

Doch das ist in Ordnung:

class MyClass extends MyTrait { 
    def apply[String](input:()=>String) = new String("foo") 
} 

Also in welchen Fällen nicht scalac wissen eigentlich die Umwandlung getan werden muss, und in In welchen Fällen nicht?

Außerdem, auch wenn ich den gesamten Pfad zu dem Typ java.lang.String schreiben

class MyClass extends MyTrait { 
    def apply[java.lang.String](input:()=>java.lang.String) = new java.lang.String("foo") 
} 

Es wirft einen weiteren Fehler:

Error:(25, 21) ']' expected but '.' found. 
     def apply[java.lang.String](input:()=>java.lang.String) = new java.lang.String("foo") 
        ^

Wenn ich wirklich wollte es dieses letztere tun Weise, indem ich direkt java.lang.String template, wie würde ich es tun?

+1

'def apply [String]' Hier deklarieren Sie einen Typparameter namens 'String'. –

Antwort

3

Diese

class MyClass extends MyTrait { 
    def apply[String](input:()=>String) = new String("foo") 
} 

ist nicht in Ordnung. Es ergibt sich class type required but String found. Das Problem hierbei ist, dass Sie nicht deklarieren, was ein Typparameter ist, wenn Sie eine Klasse mit einer parametrisierten Methode erweitern. Sie deklarieren es, wenn Sie die Methode verwenden.

Lasst uns, dass umschreiben:

class MyClass extends MyTrait { 
    def apply[String](input:()=>String) = input() 
} 

Jetzt beobachten:

scala> (new MyClass).apply[String](() => "foo") 
res0: String = foo 

scala> (new MyClass).apply[Int](() => 5) 
res1: Int = 5 

Es funktioniert, weil, wenn Sie dies erklärt:

def apply[String](input:()=>String) = input() 

String ist der Name des Parameters. Wenn Sie T, Xyzzy oder ManISuckAtTypeParameters anstelle von String oben geschrieben haben, wäre es genau das gleiche. Sie sagen, Sie erhalten einen Typparameter, Sie werden Name der Typ Parameter String, und das ist der Wert der Rückgabe-Funktion und, durch Überschreibung, der apply Methode.

Als ich apply[Int](() => 5) anrufen, wird Scala mit IntString in der Definition ersetzen.

+0

Hoppla, das war wirklich dumm von mir. Danke für die tolle Antwort. – ChoppyTheLumberjack

Verwandte Themen