Search code examples
scalascala-java-interop

Scala class implementing Java interface - double definition with same erasure


I hava a Java interface:

public interface FooJava {
    void consume(String... strings);
    void consume(Integer... ints);
}

and I want to implement it in Scala:

class BarScala extends FooJava {
  override def consume(strings: String*): Unit = ???
  override def consume(ints: Integer*): Unit = ???
}

Unfortunately this fails with:

double definition:
override def consume(strings: String*): Unit at line 4 and
override def consume(ints: Integer*): Unit at line 5
have same type after erasure: (strings: Seq)Unit
  override def consume(ints: Integer*): Unit = ???

I am aware that Java compiler creates Bridge methods, and Scala compiler does not do that.

I tried an approach with DummyImplicits: Are DummyImplicits used, and if so, how?, but it obviously fails - consume(ints: Integer*)(implicit i: DummyImplicit) overrides nothing

class BarScala extends FooJava {
  override def consume(strings: String*): Unit = ???
  override def consume(ints: Integer*)(implicit i: DummyImplicit): Unit = ???
}

I don't own the Java interface. Is is possible to implement it in Scala? I'm on Scala 2.12


Solution

  • You can implement interface with intermediate abstract class in Java and extend this abstract class in Scala

    abstract class FooJavaImpl implements FooJava {
        public abstract void consumeInts(Integer... ints);
    
        @Override
        public void consume(Integer... ints) {
            consumeInts(ints);
        }
    }
    
    class BarScala extends FooJavaImpl {
      override def consume(strings: String*): Unit = ???
      def consume(ints: Integer*)(implicit i: DummyImplicit): Unit = ???
      override def consumeInts(ints: Integer*): Unit = consume(ints: _*)
    }
    

    Or without DummyImplicit

    abstract class FooJavaImpl implements FooJava {
        public abstract void consumeInts(Integer... ints);
    
        public abstract void consumeStrs(String... strs);
    
        @Override
        public void consume(Integer... ints) {
            consumeInts(ints);
        }
    
        @Override
        public void consume(String... strs) {
            consumeStrs(strs);
        }
    }
    
    class BarScala extends FooJavaImpl {
      override def consumeInts(ints: Integer*): Unit = ???
      override def consumeStrs(strs: String*): Unit = ???
    }