4

I am using a Java library in my Scala project which has an interface that looks like this:

public interface A extends Comparable {
    String getSomething();
}

Note how the library implementation does not specify any specific type for Java's Comparable<T> interface.

In my Scala code I want to create an instance of A like so:

object AFactory {
  def getA: A = new A {
    override def getSomething: String = "test"
    override def compareTo(o: ???): Int = -1
  }
}

Unfortunately, I am not sure what type to specify for ???. Does anyone know how can I implement this interface and get it to compile?

Tobi
  • 1,492
  • 1
  • 13
  • 20
  • 2
    Maybe try `Any`? – Krzysztof Atłasik Nov 14 '19 at 08:54
  • 2
    I don't know enough Scala to help with that, but a generic type without a type parameter is called a "raw type" (and is strictly just for backwards compatible, modern code should never use them). Maybe that helps you google for a solution. – Joachim Sauer Nov 14 '19 at 08:54
  • Does the IDE create something useful when you let it auto-complete `override` ? The compile error when the method is missing may also be informative. – Thilo Nov 14 '19 at 08:56
  • 3
    Looks like it might not be possible: https://www.scala-lang.org/old/node/6666 – Brian McCutchon Nov 14 '19 at 09:09
  • 2
    Raw types are for pre 1.5 Java compatibility. They are bad. Stop using them. See also https://typelevel.org/blog/2015/02/26/rawtypes.html – cbley Nov 14 '19 at 09:53
  • You might want to check https://www.scala-lang.org/api/2.12.0/scala/math/Ordered.html. I also added a snippet here https://scastie.scala-lang.org/x0ofkQhERRCMdlGc8lTQwQ for you to visualize it. – blasrodri Nov 14 '19 at 10:31
  • Thanks all, I should have added the compile error and explained what I tried. If I auto-complete with the IDE the suggested type is `T` which obviously does not compile. Changing `T` to `Any` leads to: ```method compareTo overrides nothing. Note: the super classes of <$anon: A> contain the following, non final members named compareTo: def compareTo(x$1: T): Int override def compareTo(o: Any): Int = -1``` and ```object creation impossible. Missing implementation for: def compareTo(x$1: T): Int // inherited from trait Comparable def getA: A = new A {``` – Tobi Nov 14 '19 at 10:42
  • I am not the author of the library that contains interface `A` so I can't change the declaration, unfortunately. According to a comment in the link shared by @BrianMcCutchon it seems that it may not possible to implement this interface. – Tobi Nov 14 '19 at 10:50
  • Here are some additional links that suggest that there is no solution to this: https://github.com/scala/bug/issues/2091 https://michid.wordpress.com/2009/08/30/implementing-java-interfaces-and-generics/ https://michid.wordpress.com/2009/06/24/puzzle-implement-this-solution/ – Tobi Nov 14 '19 at 11:03

1 Answers1

3

There is no direct way to do it. One way to make you code run against pre-java5 code, is to have Java bridge methods:

public abstract class B implements A {
    @Override
    public int compareTo(Object o) {
        return 0;
    }
}

object AFactory {
  def getA: A = new B {
    override def getSomething: String = "test"
  }
}

If you not want to have the compareTo implemented in Java. You could may be introduce a bridge method and implement the bridge method in scala:

public abstract class B implements A {
    @Override
    public int compareTo(Object o) {
        return compareToBridge(o);
    }

    protected abstract int compareToBridge(Object o);
}

object AFactory {
  def getA: A = new B {
    override def getSomething: String = "test"

    override def compareToBridge(o: Any): Int = ???
  }
}

Without using bridge methods, I dont think there is a nicer way of solving this problem.

Jatin
  • 31,116
  • 15
  • 98
  • 163
  • Here is a similar ticket to this problem: https://stackoverflow.com/questions/21473614/implementing-multilevel-java-interfaces-in-scala/21473821#21473821 – Jatin Nov 14 '19 at 11:52