2
votes

I have a Java interface which uses an intersection type like this:

public interface JavaIntersection{
    public <E extends JComponent & Runnable> void foo(E arg);
}

and I'm trying to create a Scala class which implements this interface. So I wrote the following:

class ScalaIntersection extends JavaIntersection{
  override def foo[E <: JComponent with Runnable](arg:E):Unit = ???
}

This works but, in the full program I'm writing, this type gets used in multiple places. Having to include the full type each time would be pretty tedious. So I modified the class like this:

class ScalaIntersection extends JavaIntersection{
  type RunnableComponent <: JComponent with Runnable
  override def foo(arg:RunnableComponent):Unit = ???
}

With this change the program no longer compiles, with the following errors:

error: class ScalaIntersection needs to be abstract, since method foo in trait JavaIntersection of type [E <: javax.swing.JComponent with Runnable](arg: E)Unit is not defined

error: method foo overrides nothing.
[INFO] Note: the super classes of class ScalaIntersection contain the following, non final members named foo:
[INFO] def foo[E <: javax.swing.JComponent with Runnable](arg: E): Unit

Is there a way in Scala to implement an interface whose method takes a class implementing another interface, without needing to write the entire type on every method?

1

1 Answers

4
votes

This error arises because you've removed the type parameter, and thus the signature of the method you are trying to implement. The compiler then sees that you haven't implemented the original method in question:

error: class ScalaIntersection needs to be abstract, since method foo in trait JavaIntersection of type [E <: javax.swing.JComponent with Runnable](arg: E)Unit is not defined

You cannot really use a type alias to remove both the long type name and the type parameter of a method of which that type is the upper-bound (at least not with that syntax). Instead, make the type alias exactly that intersection type. I don't see a way to lose the type parameter completely, as the method you are implementing requires it.

class ScalaIntersection extends JavaIntersection {
  type RunnableComponent = JComponent with Runnable
  override def foo[E <: RunnableComponent](arg: E): Unit = ???
}