3

Assume there is a base class in a Java library which cannot be modified

public class BaseClass {
    public Something function(int... args){ ... }
}

Typically, this would be overridden in Scala by using the Scala varargs syntax:

class TypicalScalaVarargsOverrideClass extends BaseClass {
  override def function(args: Int*): Something = { ... }
}

But if TypicalScalaVarargsOverrideClass.function is invoked in Java code, a no suitable method error is raised:

// no args
no suitable method found for function(no arguments)
    method TypicalScalaVarargsOverrideClass.function(scala.collection.Seq<java.lang.Object>) is not applicable
      (actual and formal argument lists differ in length)
    method TypicalScalaVarargsOverrideClass.function(int[]) is not applicable
      (actual and formal argument lists differ in length)

// 1 arg
no suitable method found for function(int)
    method TypicalScalaVarargsOverrideClass.function(scala.collection.Seq<java.lang.Object>) is not applicable
      (argument mismatch; int cannot be converted to scala.collection.Seq<java.lang.Object>)
    method TypicalScalaVarargsOverrideClass.function(int[]) is not applicable
      (argument mismatch; int cannot be converted to int[])

// 3 args
no suitable method found for function(int,int,int)
    method TypicalScalaVarargsOverrideClass.function(scala.collection.Seq<java.lang.Object>) is not applicable
      (actual and formal argument lists differ in length)
    method TypicalScalaVarargsOverrideClass.function(int[]) is not applicable
      (actual and formal argument lists differ in length)

Typically, the solution to this is to add @varargs annotation, making the bytecode generated from the Scala code compatible the Java:

class UsingVarargsAnnotationClass extends BaseClass {
  @varargs
  override def function(args: Int*): Something = { ... }
}

But this results in a double definition error, as it now collides with the original function definition:

double definition:
override def function(args: Int*): Something at line 1 and
override def function(args: Array[Int]): Something at line 3
have same type after erasure: (args: Array[Int])Something
  override def function(args: Int*): Something = {

So is there a way, in Scala (specifically 2.12 or 2.13), to define an override of a Java varargs method which is still callable from both Scala and Java?

The primary suggestion I've received is to avoid this entirely by defining the interface of the override class in Java, with the override methods making a call to some delegate function defined in Scala (there are a few ways to do that).

3
  • 1
    Haven't tried, doesn't override def function(args: Array[Int]) in Scala work? Commented Jun 18 at 17:53
  • Scala does not see that function as overriding anything. Without the override, Scala does not call that function when passed variadic arguments (it calls the BaseClass method), and the variadic method is not callable at all from java. Commented Jun 18 at 19:11
  • 4
    Looks to be a known issue in Scala 2.12-13 that has no fix as this looks to be a compiler problem with regards to projecting types in Scala to Java ie the Scala Int type is projected as an Object instead of the primitive int type that's expected for the super class Commented Jun 19 at 6:39

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.