На объекте ValueSet у меня есть apply(pairs : (String, ValueBase)*)
и неявные преобразования из Int и String в ValueBase. Если я применяю ValueSet("a" -> 1, "b" -> 2)
, то пары (String, Int)
конвертируются в (String, ValueBase)
, и это прекрасно работает. Если я подаю заявку только с одной парой, ValueSet("a" -> 1)
, то это говорит о том, что перегрузка при подаче заявки на (String,Int)
не перегружена, то есть не будет неявного преобразования. Я могу взломать это, добавив apply[V <% ValueBase](p : (String, V))
, который работает в случае одной пары.
Почему apply(pairs : (String, ValueBase)*)
не работает только с одной парой?
(Бонусный вопрос: добавление дополнительного apply (), кажется, решает проблему - есть ли лучшее решение? Что-то не так с этим решением?)
Вот полный скомпилированный пример, упрощенный от моего реального кода, чтобы попытаться показать минимальную проблему.
class ValueBase
case class ValueInt(val value : Int) extends ValueBase
case class ValueString(val value : String) extends ValueBase
case class ValuePair(val key : String, val value : ValueBase)
case class ValueSet(val value : List[ValuePair]) extends ValueBase
object ValueSet {
def apply(pairs : (String, ValueBase)*) : ValueSet = {
ValueSet(pairs.map(p => ValuePair(p._1, p._2)).toList)
}
/* Commenting out this apply() means single-pair
* ValueSet("a" -> 1)
* will not compile, error is:
* overloaded method value apply with alternatives: (value: List[ValuePair])ValueSet <and> (pairs: (String, ValueBase)*)ValueSet cannot be applied to ((java.lang.String, Int))
* Why does (String,Int) implicit convert to (String,ValueBase) if there are two args but not if there's one?
* Why do I need this apply()?
*/
def apply[V <% ValueBase](p : (String, V)) : ValueSet = {
ValueSet(List(ValuePair(p._1, p._2)))
}
}
object Sample {
implicit def int2value(i : Int) = ValueInt(i)
implicit def string2value(s : String) = ValueString(s)
/* These samples show the goal, to construct the sets
* in a nice Map-literal sort of style
*/
val oneInt = ValueSet("a" -> 1)
val oneString = ValueSet("b" -> "c")
val twoInt = ValueSet("d" -> 2, "e" -> 3)
val twoTypes = ValueSet("f" -> 4, "g" -> "quick brown fox")
/* Taking ArrowAssoc out of the picture and typing "Pair"
* explicitly doesn't seem to matter
*/
val oneInt2 = ValueSet(Pair("a", 1))
val twoTypes2 = ValueSet(Pair("f", 4), Pair("g", "quick brown fox"))
}