Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala/Java interoperability: How to deal with options containing Int/Long (primitive types)?

Given a service in Scala:

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

which is to be used from 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
        }

    }
}

I'd like to avoid to treat primitive and non-primitive types in a different way.

So I tried to get around this by adding another method:

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

but this requires a different name for the method. As this could be confusing from the caller's perspective, are there any other possibilities?

I'm using Scala 2.10.1, and Java 1.6

like image 402
Beryllium Avatar asked Oct 03 '22 20:10

Beryllium


1 Answers

The solution I am going to test is to use a DummyImplicit, so I can have the same method name for both the Scala and the Java method:

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

to be used from Scala like this:

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

and from 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);
        }
    }

}
like image 67
Beryllium Avatar answered Oct 07 '22 20:10

Beryllium