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
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.
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")
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)
}
}
© 2024 OneMinuteCode. All rights reserved.