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 ++?



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?

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.


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.


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");
    }

}

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.


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ć.


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.


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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.