如何在 Scala 中消除具有 vararg 和不具有 vararg 的方法之间的歧义

2022-09-01 20:44:40

我正在尝试使用Scala的java jcommander库。java JCommander 类具有多个构造函数:

 public JCommander(Object object)  
 public JCommander(Object object, ResourceBundle bundle, String... args)   
 public JCommander(Object object, String... args)   

我想调用第一个带 varargs 的构造函数。我试过了:

jCommander = new JCommander(cmdLineArgs)

我收到错误:

error: ambiguous reference to overloaded definition,
both constructor JCommander in class JCommander of type (x$1: Any,x$2: <repeated...>[java.lang.String])com.beust.jcommander.JCommander
and  constructor JCommander in class JCommander of type (x$1: Any)com.beust.jcommander.JCommander
match argument types (com.lasic.CommandLineArgs) and expected result type com.beust.jcommander.JCommander
jCommander = new JCommander(cmdLineArgs)

我也尝试过使用命名参数,但得到了相同的结果:

jCommander = new JCommander(`object` = cmdLineArgs)

我如何告诉Scala我想调用不采用varargs的构造函数?

我使用的是Scala 2.8.0。


答案 1

抱歉,我现在意识到这是Java的一个已知的互操作性问题。请参阅此问题票证。我所知道的唯一解决方法是创建一个小的Java类来消除这些调用的歧义。


答案 2

我知道这个问题的唯一 Scala 解决方案涉及反思。

不明确的方法

假设我们有一个 Java 测试类:

public class Ambig {
  public Ambig() {}
  public String say(Object o) { return o.toString(); }
  public String say(Object o, String... ss) { return o.toString()+ss.length; }
}

我们可以通过反射直接访问该方法:

val ambig = new Ambig
val methods = ambig.getClass.getMethods.filter(_.getName == "say")
val wanted = methods.find(_.getParameterTypes.length == 1).get
wanted.invoke(ambig, Some(5)).asInstanceOf[String]

或者我们可以使用结构类型(在引擎盖下使用反射)以更少的样板实现相同的目标:

def sayer(speaker: { def say(o: Object): String }, o: Object) = speaker.say(o)
sayer(new Ambig, Some(5))

不明确的构造函数

我们的策略必须有所不同,因为我们实际上没有一个对象可以开始。假设我们有 Java 类

public class Ambig2 {
  public final String say;
  public Ambig2(Object o) { say = o.toString(); }
  public Ambig2(Object o, String... ss) { say = o.toString()+ss.length; }
}

结构类型方法不再有效,但我们仍然可以使用反射:

val mkAmbig2 = classOf[Ambig2].getConstructors.filter(_.getParameterTypes.length==1)
val ambig = mkAmbig2.head.newInstance(Some(5)).asInstanceOf[Ambig2]
ambig.say   // Some(5)

推荐