Java - почему нет метода перегрузки на основе возвращаемого типа? - PullRequest
42 голосов
/ 30 апреля 2010

Я знаю, что это невозможно, но кто-нибудь может предложить теорию о том, почему Java решила не поддерживать это? Я спрашиваю, потому что я только что столкнулся с ситуацией, когда я думаю , что было бы хорошо иметь.

Ответы [ 9 ]

75 голосов
/ 30 апреля 2010

Поскольку вам не требуется захватывать возвращаемое значение метода в Java, в этом случае компилятор не может решить, какую перегрузку использовать. Э.Г.

boolean doSomething() { ... }

int doSomething() { ... }

doSomething(); // which one to call???
31 голосов
/ 19 июня 2011

Одним интересным аспектом этого вопроса является тот факт, что язык Java запрещает перегрузку методов только по типу возвращаемого значения. Но не JVM:

Обратите внимание, что может быть более одного метод сопоставления в классе, потому что в то время как язык Java запрещает класс для объявления нескольких методов с та же подпись, но другая возвращаемые типы, виртуальная машина Java не. Это увеличенная гибкость в виртуальной машине можно использовать для реализовать различные языковые функции. Например, ковариантный возврат может быть реализовано с помощью мостовых методов; метод моста и метод, являющийся переопределено будет иметь то же самое подпись, но разные типы возврата.

От: Class.getMethod (String, Class ...)

14 голосов
/ 30 апреля 2010

Я удивился, почему они тоже не поддерживают это. Конечно, если вы проигнорируете возвращаемое значение, компилятор не сможет узнать, что вы хотите. Но это та же неясность, которая возникает при прохождении нулей. Как:

String doSomething(String s) { ... }
String doSomething(Integer s) { ... }
...
String out=doSomething(null);

В этом случае компилятор просто жалуется, что вызов неоднозначный, и вы должны разрешить его, передав нулевое значение, например:

String out=doSomething((String)null);

Вы можете сделать то же самое с перегрузкой по типу возврата:

String getSomething() { ... }
Integer getSomething() { ... }
...
Integer n=getSomething();

предположительно вызовет вторую функцию.

getSomething();

будет неоднозначным (и в этом примере, вероятно, бесполезным, если у него нет побочных эффектов, но это уже другая история), так что вам придется сказать:

(String) getSomething();

Более реалистично, возможно:

if ((String) getSomething()==null) ...

Но это простой случай. Я вижу, что компилятор не хочет поддерживать это, потому что это может быть очень сложно понять, кроме простого назначения. Например, рассмотрим:

String getSomething() { ... };
Integer getSomething() { ... };
String getOtherthing() { ... };
...
if (getSomething().equals(getOtherthing())) ...

Компилятор должен выяснить, что и String, и Integer имеют функции равенства, поэтому любой из них допустим в этой точке. Тогда следует заметить, что getOtherthing является строкой, а Integer.equals (String) маловероятен, поэтому, вероятно, автор хотел получить String.equals (String). Выполнимо, но в этот момент я начинаю понимать, что в общем случае это может быть зверь.

А затем предположим, что мы добавляем:

Integer getOtherthing() { ... };

Что теперь делает компилятор с этим оператором IF? Он может использовать строковые версии обеих функций или Integer, но не String одной и Integer другой. В этот момент он должен был настаивать на актерском составе, чтобы сказать, что, я думаю. Но сложность действительно выходит из-под контроля.

И если компилятору сложно понять, что вы на самом деле имеете в виду, представьте, как бы это выглядел для другого программиста, который не может просмотреть все сигнатуры функций так быстро, как это может сделать компилятор.

3 голосов
/ 30 апреля 2010

Хотя это теоретически возможно, он не использовался в Java по той же причине, по которой он не использовался в C ++; а именно, было обнаружено, что перегрузки, основанные на возвращаемых типах, обычно более запутаны для разработчиков, преимущество незначительно по сравнению с затратами на его реализацию, и это было бы неоднозначным в случае, когда возвращаемый тип не назначается значение. По этим причинам перегрузка на основе возвращаемого типа не поддерживается.

3 голосов
/ 30 апреля 2010

Это потому, что вы можете игнорировать возвращаемое значение.

1 голос
/ 30 апреля 2010

Я думаю, что одной из причин является то, что в большинстве случаев вы можете определить тип возвращаемого значения функции только после выполнения функции, а не перед этим процессом.Таким образом, это не может помочь вам решить, какую перегруженную функцию вызывать только на основе различных типов возвращаемых функций.

0 голосов
/ 15 августа 2018

В методе перегрузки используется метод полиморфизма времени компиляции. Переопределение метода использует технику полиморфизма времени выполнения.

Метод перегрузки:

Как сказано в предыдущих ответах, java не поддерживает перегрузку методов с другим типом возвращаемого значения и одинаковыми аргументами. Это потому, что он должен определить, какой метод использовать во время компиляции. Чтобы устранить неоднозначность, они разработали метод перегрузки метода следующим образом.

Если нам действительно нужна перегрузка метода разными типами и одинаковыми аргументами, это возможно в некоторой степени при переопределении метода.

Переопределение метода:

Переопределение метода использует технику полиморфизма во время выполнения. Следовательно, какой метод для выполнения не решается во время компиляции, и это решается во время выполнения JVM.

С ко-вариантными типами возврата мы можем иметь другой тип возвращаемого значения в методе подкласса с теми же аргументами, что и у базового класса.

Пример ко-варианта возврата:

            class BaseClass {
                BaseClass dosomething(){
                    System.out.println("Print BaseClass");
                    return this;
                }

            }

            class AnotherBaseClass extends BaseClass {
                @Override
                BaseClass dosomething(){
                    System.out.println("Print AnotherBaseClass");
                    return this;
                }
            }



            class SubClass extends AnotherBaseClass {
                @Override
                SubClass dosomething(){ /*Here SubClass is co-vairantreturn type*/ 
                    System.out.println("Print SubClass");
                    return this;
                }
                public static void main(String args[]){
                  SubClass s1 = new SubClass();
                  s1.dosomething();
                }
            }

Выход:

Print SubClass

0 голосов
/ 10 апреля 2012
Перегрузочная функция

только на основе возвращаемого типа вводит в заблуждение то, что компилятор делает различие между вызовами, потому что во время вызова вы не указываете тип возврата, как в случае с параметрами, поэтому вы даете только Список параметров и этот список параметров - единственный способ для компилятора различать вызовы функции, и возвращаемое значение принимается при завершении функции, поэтому тип возвращаемого значения не влияет на сигнатуру функции

0 голосов
/ 16 июня 2010

Поскольку Java может приводить значение возвращаемого типа к целевой переменной, поэтому она не знает, в какой тип переменной вы сохраняете возвращаемое значение функции.

...