Chociaż mogą istnieć prawidłowe przypadki, w których takie przeciążenia metod mogą stać się niejednoznaczne, dlaczego kompilator nie zezwala na kod, który nie jest niejednoznaczny w czasie kompilacji ani w czasie wykonywania?
Przykład:
// 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 ...
Czy są jakieś powody, dla których nie można nieco poluzować tych ograniczeń?
Zwłaszcza podczas konwersji mocno przeciążonego kodu Javy na domyślne argumenty Scali są bardzo ważne i nie jest przyjemnie dowiedzieć się po zastąpieniu wielu metod Javy jedną z metod Scali, że specyfikacja / kompilator nakłada dowolne ograniczenia.
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");}
Odpowiedzi:
Chciałbym zacytować Lukasa Rytza ( stąd ):
Rozwiązaniem dla przyszłej wersji Scali mogłoby być włączenie nazw typów argumentów innych niż domyślne (te na początku metody, które ujednoznaczniają przeciążone wersje) do schematu nazewnictwa, np. W tym przypadku:
byłoby to coś takiego:
Ktoś chętny do napisania propozycji SIP ?
źródło
A with B
, na przykład?Byłoby bardzo trudno uzyskać czytelną i dokładną specyfikację dla interakcji rozdzielczości przeciążenia z domyślnymi argumentami. Oczywiście w wielu indywidualnych przypadkach, jak ten tutaj przedstawiony, łatwo powiedzieć, co powinno się wydarzyć. Ale to nie jest wystarczające. Potrzebowalibyśmy specyfikacji, która decyduje o wszystkich możliwych przypadkach narożnych. Rozdzielczość przeciążenia jest już bardzo trudna do określenia. Dodanie domyślnych argumentów do miksu jeszcze bardziej utrudniłoby sprawę. Dlatego zdecydowaliśmy się oddzielić te dwie rzeczy.
źródło
Nie mogę odpowiedzieć na Twoje pytanie, ale oto obejście:
Jeśli masz dwie bardzo długie listy argumentów, które różnią się tylko jednym argumentem, może to być warte zachodu ...
źródło
Either
a nie tylko dofoo
- w ten sposób, gdyEither[A, B]
żądana jest wartość, zarównoA
iB
są akceptowane. Zamiast tego należy zdefiniować typ, który jest akceptowany tylko przez funkcje z domyślnymi argumentami (jakfoo
tutaj), jeśli chcesz iść w tym kierunku; oczywiście staje się jeszcze mniej jasne, czy jest to wygodne rozwiązanie.Udało mi się przedefiniować (w stylu Java) metody przeciążania.
Zapewnia to kompilatorowi żądaną rozdzielczość zgodnie z obecnymi parametrami.
źródło
Oto uogólnienie odpowiedzi @Landei:
Czego naprawdę chcesz:
Obejście problemu
źródło
Jednym z możliwych scenariuszy jest
Kompilator nie będzie wiedział, który wywołać. Aby zapobiec innym możliwym zagrożeniom, kompilator pozwoliłby, aby co najwyżej jedna przeciążona metoda miała domyślne argumenty.
Zgaduję :-)
źródło
Rozumiem, że mogą wystąpić kolizje nazw w skompilowanych klasach z domyślnymi wartościami argumentów. Widziałem coś podobnego, wspomnianego w kilku wątkach.
Nazwana specyfikacja argumentu jest tutaj: http://www.scala-lang.org/sites/default/files/sids/rytz/Mon,%202009-11-09,%2017:29/named-args.pdf
W Stanach:
Tak więc na razie to nie zadziała.
Możesz zrobić coś takiego, co możesz zrobić w Javie, na przykład:
źródło