Bien qu'il puisse y avoir des cas valides où de telles surcharges de méthodes pourraient devenir ambiguës, pourquoi le compilateur interdit-il le code qui n'est ni ambigu au moment de la compilation ni au moment de l'exécution?
Exemple:
// This fails:
def foo(a: String)(b: Int = 42) = a + b
def foo(a: Int) (b: Int = 42) = a + b
// This fails, too. Even if there is no position in the argument list,
// where the types are the same.
def foo(a: Int) (b: Int = 42) = a + b
def foo(a: String)(b: String = "Foo") = a + b
// This is OK:
def foo(a: String)(b: Int) = a + b
def foo(a: Int) (b: Int = 42) = a + b
// Even this is OK.
def foo(a: Int)(b: Int) = a + b
def foo(a: Int)(b: String = "Foo") = a + b
val bar = foo(42)_ // This complains obviously ...
Y a-t-il des raisons pour lesquelles ces restrictions ne peuvent pas être un peu assouplies?
Surtout lors de la conversion de code Java fortement surchargé en arguments par défaut Scala est très important et il n'est pas agréable de savoir après avoir remplacé de nombreuses méthodes Java par une méthode Scala que la spécification / compilateur impose des restrictions arbitraires.
object Test { def a[A](b: Int, c: Int, d: Int = 7): Unit = {}; def a[A](a:String, b: String = ""): Unit = {}; a(2,3,4); a("a");}
Réponses:
Je voudrais citer Lukas Rytz (à partir d' ici ):
Une solution pour la future version de Scala pourrait être d'incorporer les noms de type des arguments non par défaut (ceux au début d'une méthode, qui éliminent l'ambiguïté des versions surchargées) dans le schéma de nommage, par exemple dans ce cas:
ce serait quelque chose comme:
Quelqu'un est-il prêt à rédiger une proposition SIP ?
la source
A with B
, par exemple?Il serait très difficile d'obtenir une spécification lisible et précise pour les interactions de résolution de surcharge avec les arguments par défaut. Bien sûr, pour de nombreux cas individuels, comme celui présenté ici, il est facile de dire ce qui doit se passer. Mais ce n'est pas assez. Nous aurions besoin d'une spécification qui décide de tous les cas de coin possibles. La résolution de surcharge est déjà très difficile à spécifier. L'ajout d'arguments par défaut dans le mix rendrait les choses encore plus difficiles. C'est pourquoi nous avons choisi de séparer les deux.
la source
Je ne peux pas répondre à votre question, mais voici une solution de contournement:
Si vous avez deux très longues listes d'arguments qui diffèrent par un seul argument, cela pourrait valoir la peine ...
la source
Either
et non seulement pour lesfoo
- de cette façon, chaque fois qu'uneEither[A, B]
valeur est demandée, à la foisA
etB
sont acceptées. Il faut plutôt définir un type qui n'est accepté que par les fonctions ayant des arguments par défaut (commefoo
ici), si vous voulez aller dans cette direction; bien sûr, il devient encore moins clair s'il s'agit d'une solution pratique.Ce qui a fonctionné pour moi, c'est de redéfinir (style Java) les méthodes de surcharge.
Cela garantit au compilateur la résolution souhaitée en fonction des paramètres actuels.
la source
Voici une généralisation de la réponse @Landei:
Ce que vous voulez vraiment:
Solution de contournement
la source
L'un des scénarios possibles est
Le compilateur ne sait pas lequel appeler. Pour prévenir d'autres dangers possibles, le compilateur autoriserait au plus une méthode surchargée à avoir des arguments par défaut.
Juste mon avis :-)
la source
Je crois comprendre qu'il peut y avoir des collisions de noms dans les classes compilées avec des valeurs d'argument par défaut. J'ai vu quelque chose de ce genre mentionné dans plusieurs fils.
La spécification de l'argument nommé est ici: http://www.scala-lang.org/sites/default/files/sids/rytz/Mon,%202009-11-09,%2017:29/named-args.pdf
Il est dit:
Donc, pour le moment en tout cas, cela ne fonctionnera pas.
Vous pouvez faire quelque chose comme ce que vous pourriez faire en Java, par exemple:
la source