Единственное известное мне решение этой проблемы от 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)