2016-05-11 19 views
2

In Scala mache ich einige Java-Interop. Ich erstelle einen Wert der Klasse Sample.Individual und ich rufe eine statische Java-Methode wie Sample.Individual.newBuilder(). Ich verwende ein paar Klassen, die alle dieselbe statische Methode haben (zB: Sample.Position und Sample.Feature). Ich möchte eine Funktion machen, die über sie parametrisiert, so etwas wie:Zugriff auf statische Methoden parametrisierter Java-Klassen von Scala

Was ist der richtige Weg ist, die Art Sample.Individual, die mich parametrieren lässt:

def p[T](s: String): T = { 
    val pb = T.newBuilder() // this returns a value of type T.Builder 
    ... do stuff with pb ... 
    pb.build() // this returns a value of type T 
} 

aber das sagt mir, „Wert T nicht gefunden“ Rufen Sie auch statische Methoden auf, die in Scala enthalten sind?

+0

Scala * könnte * Zucker dafür haben, aber es würde Laufzeit-Reflektion benötigen, um tatsächlich zu implementieren, da es den normalen dynamischen Versand nicht verwenden konnte. – chrylis

+1

Ich glaube nicht, dass es einen direkten Weg gibt, das zu tun. Zumindest nicht wie du gezeigt hast. Sie können jedoch ['TypeTags/ClassTags'] (http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html) verwenden, um weitere Informationen über den Typ zu erhalten, der bearbeitet wird, und dann [Java Reflections API] zu verwenden ] (https://docs.oracle.com/javase/tutorial/reflect/) um [die statische Methode aufzurufen] (http://stackoverflow.com/questions/2467544/invoking-a-static-method-using-reflection)). – marcospereira

Antwort

1

Ich würde dringend empfehlen, dass Sie nicht mit dieser Idee weitermachen. Selbst wenn Sie einen Weg finden, es zu tun, ist es nicht idiomatische Scala. Es ist aus der Ferne möglich, ein paar Zeilen Code zu entfernen, aber Sie verlieren an Lesbarkeit und Leistung. schlechter Kompromiss.

Das Problem, das Sie haben sind, ist, dass Sie Ihre p Funktion ein Typparameter T, du geben und dann den Aufruf des newBuilder Methode auf diese Art T. Das kannst du nicht, denn Scala weiß nichts über deinen Typ T.

Stattdessen lernen Sie zuerst ein wenig mehr über diese Java-Typen. Haben alle potenziell konstruierten Klassen einen gemeinsamen Typ? Wenn nicht, haben Sie kein Glück (Sie sind technisch kein Glück, wenn Sie die Bibliothek, die Sie verwenden, aufpimpen, aber bitte nicht: P).

Andernfalls importieren Sie nur diese Typen (einschließlich der generischen). Fügen Sie den generischen Typ als den Typ Ihrer -Funktion ein und passen Sie die Zeichenfolge an, und instanziieren Sie dann Ihren Typ. Strings können was auch immer sein, also möchten Sie wahrscheinlich eher einen Option[GenericClass] als einen GenericClass zurückgeben.

z.B.

import xxx.GenericClassBuilder 
import xxx.GenericClass 
import xxx.ClassA 
import xxx.ClassB 

def p(s: String): Option[GenericClass] = { 
    val maybePb: Option[GenericClassBuilder] = s match { 
     case "ClassA" => Some(ClassA.newBuilder()) 
     case "ClassB" => Some(ClassB.newBuilder()) 
     case _ => None 
    } 
    maybePb.foreach { pb => ... do side-effecty stuff with pb ...} 
    maybePb.map(_.build()) 
} 
+0

Danke. Als Scala-Neuling muss ich das verstehen, danke, dass du dir die Zeit genommen hast! – prismofeverything

+0

@prismofeverything dank Ihnen auch. Der Versuch, Dinge richtig zu erklären, hilft mir, sie besser zu verstehen. – mlg