Während es gültige Fälle geben kann, in denen solche Methodenüberladungen mehrdeutig werden können, warum verbietet der Compiler Code, der weder zur Kompilierungszeit noch zur Laufzeit mehrdeutig ist?
Beispiel:
// 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 ...
Gibt es Gründe, warum diese Einschränkungen nicht ein wenig gelockert werden können?
Insbesondere beim Konvertieren von stark überlastetem Java-Code in Scala sind Standardargumente sehr wichtig, und es ist nicht schön herauszufinden, dass der Spec / Compiler nach dem Ersetzen vieler Java-Methoden durch eine Scala-Methode willkürliche Einschränkungen auferlegt.
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");}
Antworten:
Ich möchte Lukas Rytz (von hier ) zitieren :
Eine Lösung für die zukünftige Scala Version könnte einzuarbeiten Typnamen der Nicht-Standard - Argumente (die am Anfang eines Verfahrens, welche Versionen überlastet disambiguate) in das Namensschema, zB in diesem Fall:
es wäre so etwas wie:
Jemand, der bereit ist , einen SIP-Vorschlag zu schreiben ?
quelle
A with B
, zum Beispiel?Es wäre sehr schwierig, eine lesbare und präzise Spezifikation für die Wechselwirkungen der Überladungsauflösung mit Standardargumenten zu erhalten. Natürlich ist es für viele Einzelfälle, wie den hier vorgestellten, leicht zu sagen, was passieren soll. Das reicht aber nicht. Wir brauchen eine Spezifikation, die alle möglichen Eckfälle entscheidet. Die Überladungsauflösung ist bereits sehr schwer anzugeben. Das Hinzufügen von Standardargumenten in der Mischung würde es noch schwieriger machen. Deshalb haben wir uns entschieden, die beiden zu trennen.
quelle
Ich kann Ihre Frage nicht beantworten, aber hier ist eine Problemumgehung:
Wenn Sie zwei sehr lange Arg-Listen haben, die sich nur in einem Arg unterscheiden, ist es möglicherweise die Mühe wert ...
quelle
Either
und nicht nur fürfoo
- diese Weise , wenn einEither[A, B]
Wert angefordert wird, beideA
undB
akzeptiert werden. Man sollte stattdessen einen Typ definieren, der nur von Funktionen mit Standardargumenten (wiefoo
hier) akzeptiert wird , wenn man in diese Richtung gehen möchte; Natürlich wird noch weniger klar, ob dies eine bequeme Lösung ist.Was für mich funktioniert hat, ist die Neudefinition (Java-Stil) der Überladungsmethoden.
Dies stellt dem Compiler sicher, welche Auflösung Sie gemäß den aktuellen Parametern wünschen.
quelle
Hier ist eine Verallgemeinerung der @ Landi-Antwort:
Was Sie wirklich wollen:
Workarround
quelle
Eines der möglichen Szenarien ist
Der Compiler wird verwirrt sein, welchen er aufrufen soll. Um andere mögliche Gefahren zu vermeiden, würde der Compiler höchstens eine überladene Methode mit Standardargumenten zulassen.
Nur meine Vermutung :-)
quelle
Nach meinem Verständnis kann es in den kompilierten Klassen mit Standardargumentwerten zu Namenskollisionen kommen. Ich habe etwas in dieser Richtung gesehen, das in mehreren Threads erwähnt wurde.
Die angegebene Argumentspezifikation finden Sie hier: http://www.scala-lang.org/sites/default/files/sids/rytz/Mon,%202009-11-09,%2017:29/named-args.pdf
Es sagt aus:
Auf jeden Fall wird es vorerst nicht funktionieren.
Sie könnten so etwas wie in Java tun, z. B.:
quelle