How can Scala explicitly resolve the ambiguity of overloaded methods?

Asked 1 years ago, Updated 1 years ago, 65 views

Scala is trying to use the overloaded method provided in Java's library.

class X {
  public<E>voidf(E...values) {System.out.println(1);}
  public void f(Object value) {System.out.println(2);}
}

However, Scala fails to resolve which of the overloaded methods to use if the parameter types are compatible.

 valx=new X()
x.f ("foo")
 error:ambiguous reference to overloaded definition,
both method fin class X of type (value: Any) Unit
and method fin class X of type [E] (values:E*) Unit
match argument types (String)

When calling, the parameters are "foo":Object or "foo".asInstanceOf[Object] and so on.You can use reflection as a workaround.

classOf[X].getMethod("f", classOf[Object]).invoke(x, "foo")//=>2

Essentially, how do I explicitly invoke the method on the 2. side in Scala?

Java 11.0.2/Scala 2.12.8

java scala

2022-09-30 20:11

3 Answers

Probably, Scala cannot invoke the setDefault(Object value) method.

With dotty (Scala 3.x), it may be possible in some way (?).
https://github.com/lampepfl/dotty/issues/5792

For the time being, I can think of about three compromises.
(I excluded how to call in reflection because it is written in the questionnaire.)

Compromise 1: Consider using another library

Compromise 2: Call the setDefault(E...value) method

With this method, I think I can call you with the following code.

arg.setDefault(Seq("foo"):_*)

However, I think the default values displayed in Help will be as follows:
(There will be extra [])

 (default: [foo])

Compromise 3: Write helper class in Java and use it in Scala

The method used by argparse4j's Scala wrapper mdekstrand/argparse4s, under src/main/java

public static void setDefault (Argument arg, Object dft)

Define a helper class with the method

and use this Java class from Scala.

/src/main/java/net/elehack/argparse4s/ArgConfig.java

package net.elehack.argparse4s;

import net.sourceforce.argparse4j.inf.Argument;

classArgConfig {
    public static void setDefault (Argument arg, Object dft) {
        arg.setDefault (dft);
    }
}

*It seems that this Scala wrapper library itself has not been maintained as of 2019.


2022-09-30 20:11

Is there a general way to avoid ambiguity?"That's not clear, but with this pattern, ""Would you like to take the type argument or not?""""Because of the difference, I think it is possible to call the variable length argument (although it is not a direct answer to the question) by specifying the type argument.

scala>net.sourceforce.argparse4j.ArgumentParsers.newFor("a").buildArgument().addArgument("b").setDefault("c")
<console>:14:error:ambiguous reference to overloaded definition,
both method setDefault into trace Argument of type [E] (x$1:E*) net.sourceforce.argparse4j.inf.Argument
and method setDefault into trace Argument of type (x$1:Any) net.sourceforce.argparse4j.inf.Argument
match argument types (String)
       net.sourceforce.argparse4j.ArgumentParsers.newFor("a").build().addArgument("b").setDefault("c")
                                                                                       ^

scala>net.sourceforce.argparse4j.ArgumentParsers.newFor("a").build().addArgument("b").setDefault [String]("c")
res0: net.sourceforce.argparse4j.inf.Argument=net.sourceforce.argparse4j.internal.ArgumentImpl @736cb954

Also, even if you call it by reflection, if you use structural subtyping on purpose as shown below, it will be a little shorter and more convenient.

.asInstanceOf[{defaultDefault(x:AnyRef)}].setDefault("c")


2022-09-30 20:11

Looking at it, it seems that there is no explicit solution in Scala's description.
In the argparse4j case, we use the return value as a method chain, so we made use of Structural Subtyping in the implicit class.

implicit class_Argument(arg:Argument){
  defaultDefault2(value:Any): Argument={//←The name is appropriate, but
    import scala.language.reflectiveCalls
    arg.asInstanceOf [{defaultDefault(value:Object):Argument}:].setDefault(value)
  }
}


2022-09-30 20:11

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.