2013-06-12 12 views
5

Biorąc usługę w Scala:Interoperacyjność Scala/Java: jak radzić sobie z opcjami zawierającymi Int/Long (typy pierwotne)?

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

który ma być używany z Java:

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 
     } 

    } 
} 

chciałbym uniknąć w leczeniu pierwotnych i innych prymitywnych typów w inny sposób.

Więc starałem się obejść ten problem poprzez dodanie innej metody:

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

ale to wymaga innej nazwy dla tej metody. Ponieważ może to być mylące z punktu widzenia dzwoniącego, czy są jakieś inne możliwości?

Używam Scala 2.10.1 i Java 1.6

Odpowiedz

2

Rozwiązanie Mam zamiar przetestować jest użycie DummyImplicit, więc mogę mieć taką samą nazwę metody zarówno dla Scala i metody Java:

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)) 
    } 

być używane od Scala tak:

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

iz 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

Podpis metoda mogłaby być nieco mylące, jak również, ale można użyć wzorca dopasowania do obsługi różnych typów - coś jak:

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) 
    } 
    } 
} 

Ponadto, nie jestem pewien o wywoływanie z java, ale może również niejawne konwersji z java.lang.Integer na Int może również działać?

+0

Dzięki za sugestie. Chciałbym udostępnić obie metody (jedną dla Scala, jedną dla Javy), obie z Int/Integer. Ponieważ istnieje wiele funkcji usługowych, powinna być krótka. Jeśli chodzi o parametry "implicit", AFAIK, muszą one być jawnie dodane w Javie. To chyba po prostu zbyt wiele wymagań :-) – Beryllium

Powiązane problemy