Przeciążenie z innym typem zwracania w Javie?

105

Dlaczego nie można przeciążać funkcji po prostu przez zmianę typu zwracanego? Czy to się zmieni w przyszłej wersji Java?

Nawiasem mówiąc, czy jest to możliwe w C ++?

nunos
źródło
KNU, ​​druga odpowiedź różni się tym, że zadaje pytanie w kategoriach ogólnych, niezwiązanych z językiem. Interesujące jest również to, że przyjęta odpowiedź na inne pytanie idzie dalej, precyzując, że Java JVM pozwala na to z manipulacją elementami wewnętrznymi.
J Woodchuck,

Odpowiedzi:

157

Nie da się tego zrobić w Javie ani w C ++. Powodem jest to, że sama wartość zwracana nie jest wystarczająca, aby kompilator mógł dowiedzieć się, którą funkcję wywołać:

public int foo() {...}
public float foo() {..}

...
foo(); // which one?
Alexander Gessler
źródło
3
Zawsze myślałem, że jeśli zrobimy coś takiego jak int i = foo () lub float f = foo (), będzie wiedział, który z nich, ale jeśli instrukcja jest tylko funkcją, której kompilator nie zna. Ja to wiem. Dzięki.
nunos
7
@nunos, nawet jeśli byłaby to liczba zmiennoprzecinkowa f = foo (), kompilator nie byłby w stanie tego rozgryźć, ponieważ obie wartości typu int byłyby prawidłowymi danymi wejściowymi dla zmiennej typu float. Porównaj zmiennoprzecinkowe f = 7; (czy 7 to float czy int?)
NomeN
5
@NomeN Ale twoje stwierdzenie sugeruje, że func (int i) i func (float i) byłyby nie do odróżnienia dla kompilatora - i wszyscy wiemy, że to nieprawda. Prawdziwy powód podaje Oded (patrz następna odpowiedź) - chodzi o podpis metody. A tak przy okazji. 7 to zdecydowanie liczba całkowita, podczas gdy 7.0 lub 7f to liczba zmiennoprzecinkowa ;-)
Ta Sas
7
7.0 nie float, to jest double.
fredoverflow
3
Fakt, że foo();bez zwracanego typu byłby niejednoznaczny, niekoniecznie jest powodem, aby zabronić tego jako przeciążenia. Istnieją argumenty, które mogą powodować niejednoznaczność (np. foo(null);), Ale nie powoduje to, że przeciążenie jest z natury nieważne.
shmosel
48

Powodem jest to, że przeciążenia w Javie są dozwolone tylko dla metod z różnymi sygnaturami .

Zwracany typ nie jest częścią podpisu metody, dlatego nie można go użyć do odróżnienia przeciążeń.

Zobacz Definiowanie metod z samouczków Java.

Oded
źródło
4
Ale dlaczego zwracany typ nie jest częścią podpisu
andho
51
och "tylko dlatego"! Widzę.
andho
3
Typ zwrotu JEST częścią sygnatury metody. Wystarczy spojrzeć na demontaż klas.
konmik
2
To naprawdę nie jest @konmik - nie według zasad przeciążania metod. Spróbuj. Ta sama nazwa metody, te same typy parametrów w tej samej kolejności, różne typy zwracane. Nie skompiluje się.
Oded
3
Tak, ponieważ zwracany typ nie jest częścią podpisu . Podpis to - nazwa metody + typy i kolejność jej parametrów. Przeczytaj link, który podałem w mojej odpowiedzi: „Podpis metody zadeklarowanej powyżej to: calculateAnswer(double, int, double, double)”. Zobacz, że zwracany typ nie jest uwzględniony, @konmik.
Oded
22

Przed Java 5.0, kiedy zastępujesz metodę, zarówno parametry, jak i zwracany typ muszą dokładnie pasować. W Javie 5.0 wprowadza nową funkcję zwaną kowariantnym typem zwrotu. Możesz przesłonić metodę z tym samym podpisem, ale zwraca podklasę zwróconego obiektu. Innymi słowy, metoda w podklasie może zwrócić obiekt, którego typ jest podklasą typu zwróconego przez metodę z tym samym podpisem w nadklasie.

Daneel S. Yaitskov
źródło
3
Byłem zaskoczony, kiedy zobaczyłem to po raz pierwszy. Dziękuję za wyjaśnienie, dlaczego jest to możliwe!
Dylan Knowles,
2
przeciążanie i nadpisywanie są różne. Przeciążenie niekoniecznie wiąże się z dziedziczeniem
senseiwu
3
Ta odpowiedź może wydawać się myląca dla nowicjusza w Javie, ponieważ w ogóle nie ma znaczenia w przypadku przeciążania , jest nadrzędna - zupełnie inna rzecz.
Azizbekian
4

Overloaded metody w java mogą mieć różne typy zwracanych wartości, biorąc pod uwagę, że argument jest inny.

Sprawdź przykładowy kod.

public class B {

    public String greet() {
        return "Hello";
    }

    //This will work
    public StringBuilder greet(String name) {
        return new StringBuilder("Hello " + name);
    }

    //This will not work
    //Error: Duplicate method greet() in type B
    public StringBuilder greet() {
        return new StringBuilder("Hello Tarzan");
    }

}
Abdullah Khan
źródło
w zasadzie typ zwrotu nie jest brany pod uwagę, tylko argumenty, smutne, ale prawdziwe
Alexander Mills
1

Kompilator nie bierze pod uwagę zwracanego typu podczas różnicowania metod, więc nie można zadeklarować dwóch metod z tym samym podpisem, nawet jeśli mają inny typ zwracany.

Ganesh
źródło
1

Zwracany typ nie ma znaczenia podczas przeciążania metody. Musimy tylko upewnić się, że nie ma dwuznaczności!

Jedynym sposobem, w jaki Java może wiedzieć, którą metodę wywołać, jest rozróżnienie typów listy argumentów. Gdyby kompilator dopuścił dwie metody o tej samej nazwie i tych samych typach argumentów, nie byłoby możliwości określenia, którą z nich powinien wywołać.

Vinayak
źródło
0

Kompilator nie bierze pod uwagę zwracanego typu podczas różnicowania metod, więc nie można zadeklarować dwóch metod z tym samym podpisem, nawet jeśli mają inny typ zwracany.

Jeśli jesteś świadomy wykonywania funkcji, będziesz świadomy, że gdy wywołujemy funkcję, część definicji wykonuje i na koniec wymagamy instrukcji return, stąd możemy powiedzieć, że powrót następuje po całej definicji funkcji, dlatego jeśli są dwa lub więcej funkcji o tej samej nazwie, tym samym typie i nr. argumentów w momencie wywołania, w jaki sposób kompilator będzie wiedział, który z nich ma zostać wywołany, ponieważ nazwa funkcji i parametry są takie same. W momencie wywołania najpierw skupiamy się na argumentach i nazwie funkcji, a po zakończeniu definicji funkcji w końcu mamy do czynienia z instrukcją return.

Błąd kompilacji jest lepszy niż błąd czasu wykonywania. Tak więc kompilator java renderuje błąd czasu kompilatora, jeśli zadeklarujesz tę samą metodę z tymi samymi parametrami.

Bhanu
źródło
Czym to się różni od zaakceptowanej odpowiedzi? (Powodem, dla którego jest to błąd czasu kompilacji, jest również to, że kompilator nie może określić, którą metodę wywołać, więc w jaki sposób ma wygenerować odpowiedni kod wykonywalny)
UnholySheep
-2

nie, naprawdę nie jest możliwe, w ten sposób możesz przeciążyć tylko przez brak argumentów lub typ danych argumentów

MAYANK AMRIT
źródło