2013-06-12 3 views
5

einen Dienst in Scala Gegeben: Scala/Java-Interoperabilität: Wie geht man mit Optionen um, die Int/Long (primitive Typen) enthalten?

public class Java { 
    public static void main(String[] args) { 
     ScalaService service = new ScalaService(); 

     // This works, but it's confusing 
     { 
      scala.Option<String> so = scala.Option.apply("Hello"); 
      scala.Option<Object> io = scala.Option.apply((Object) 10); 
      service.process1(so, io); 
     } 

     // Would be OK, but not really nice 
     { 
      scala.Option<Object> so = scala.Option.apply((Object) "Hello"); 
      scala.Option<Object> io = scala.Option.apply((Object) 10); 
      service.process1(so, io); // Does not compile 
     } 

     // The preferred way 
     { 
      scala.Option<String> so = scala.Option.apply("Hello"); 
      scala.Option<Integer> io = scala.Option.apply(10); 
      service.process1(so, io); // Does not compile 
     } 

    } 
} 

I primitiv und nicht-primitive Typen in einer anderen Art und Weise zu behandeln möchte vermeiden

:

class ScalaService { 
    def process1(s: Option[String], i: Option[Int]) { 
    println("1: " + s + ", " + i) 
    } 
} 

, die von Java verwendet werden soll.

So versuchte ich, durch das Hinzufügen eines weiteren Methode, dies zu umgehen:

def process2(s: Option[String], i: Option[java.lang.Integer]) { 
    print("2: ") 
    process1(s, i.map(v => v.toInt)) 
} 

aber dies erfordert einen anderen Namen für die Methode. Da dies aus der Sicht des Anrufers verwirrend sein könnte, gibt es noch andere Möglichkeiten?

Ich verwende Scala 2.10.1 und Java 1.6

Antwort

2

Die Lösung, die ich testen werde, ist ein DummyImplicit zu verwenden, so dass ich beide die gleichen Methodennamen der Scala und die Java-Methode für habe:

class ScalaService { 
    // To be called from Scala 
    def process(s: Option[String], i: Option[Int])(implicit d: DummyImplicit) { 
    println("1: " + s + ", " + i) 
    } 

    // To be called from Java 
    def process(s: Option[String], i: Option[java.lang.Integer]) { 
    print("2: ") 
    process(s, i.map(v => v.toInt)) 
    } 

von Scala wie folgt verwendet werden:

object ScalaService extends App { 
    val s = new ScalaService() 
    s.process(Some("Hello"), Some(123)) 
} 

und von Java:

public class Java { 
    public static void main(String[] args) { 
     ScalaService service = new ScalaService(); 

     { 
      scala.Option<String> so = scala.Option.apply("Hello"); 
      scala.Option<Integer> io = scala.Option.apply(10); 
      service.process(so, io); 
     } 
    } 

} 
2

Die Signatur der Methode wäre ein bisschen wie auch verwirrend, aber man konnte passende verwenden Muster der verschiedenen Arten zu behandeln - so etwas wie:

class ScalaService { 
    def process1(s: Option[String], i: Option[Any]) { 
    i match { 
     case Some(i2:Int) => processInternal(s, Some(i2)) 
     case Some(i2:java.lang.Integer) => processInternal(s, Some(i2.intValue)) 
     case _ => processInternal(s, None) // or throw exception if you prefer 
    } 

    def processInternal(s:Option[String], i:Option[Int]) { 
     println("1: " + s + ", " + i) 
    } 
    } 
} 

Auch bin ich nicht sicher über den Aufruf von Java, aber möglicherweise eine implizite Konvertierung von java.lang.Integer zu Int könnte auch funktionieren?

+0

Vielen Dank für Ihre Anregungen. Ich möchte beide Methoden (eine für Scala, eine für Java), beide mit Int/Integer. Da es viele Service-Funktionen gibt, sollte es kurz sein. Wie bei "impliziten" Parametern, AFAIK müssen sie explizit in Java hinzugefügt werden. Es sind wahrscheinlich einfach zu viele Anforderungen :-) – Beryllium

Verwandte Themen