Suppose I've got this Scala trait:
trait UnitThingy {
def x(): Unit
}
Providing a Java implementation is easy enough:
import scala.runtime.BoxedUnit;
public class JUnitThingy implements UnitThingy {
public void x() {
return;
}
}
Now let's start with a generic trait:
trait Foo[A] {
def x(): A
}
trait Bar extends Foo[Unit]
The approach above won't work, since the unit x
returns is now boxed, but the workaround is easy enough:
import scala.runtime.BoxedUnit;
public class JBar implements Bar {
public BoxedUnit x() {
return BoxedUnit.UNIT;
}
}
Now suppose I've got an implementation with x
defined on the Scala side:
trait Baz extends Foo[Unit] {
def x(): Unit = ()
}
I know I can't see this x
from Java, so I define my own:
import scala.runtime.BoxedUnit;
public class JBaz implements Baz {
public BoxedUnit x() {
return BoxedUnit.UNIT;
}
}
But that blows up:
[error] .../JBaz.java:3: error: JBaz is not abstract and does not override abstract method x() in Baz
[error] public class JBaz implements Baz {
[error] ^
[error] /home/travis/tmp/so/js/newsutff/JBaz.java:4: error: x() in JBaz cannot implement x() in Baz
[error] public BoxedUnit x() {
[error] ^
[error] return type BoxedUnit is not compatible with void
And if I try the abstract-class-that-delegates-to-super-trait trick:
abstract class Qux extends Baz {
override def x() = super.x()
}
And then:
public class JQux extends Qux {}
It's even worse:
[error] /home/travis/tmp/so/js/newsutff/JQux.java:1: error: JQux is not abstract and does not override abstract method x() in Foo
[error] public class JQux extends Qux {}
[error] ^
(Note that this definition of JQux
would work just fine if Baz
didn't extend Foo[Unit]
.)
If you look at what javap
says about Qux
, it's just weird:
public abstract class Qux implements Baz {
public void x();
public java.lang.Object x();
public Qux();
}
I think the problems here with both Baz
and Qux
have to be scalac bugs, but is there a workaround? I don't really care about the Baz
part, but is there any way I can inherit from Qux
in Java?
BoxedUnit.UNIT
trick lets me implement a genericUnit
method, so why does adding one level of inheritance break that? It's not like it makes the method less generic in any real way. – Dermatome