Перегрузка с другим типом возврата в Java?


105

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

Кстати, для справки, это возможно в C ++?



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

Ответы:


157

Вы не можете сделать это на Java и не можете сделать это на C ++. Обоснование состоит в том, что одного только возвращаемого значения компилятору недостаточно, чтобы определить, какую функцию вызывать:

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

...
foo(); // which one?

3
Я всегда думал, что если бы мы сделали что-то вроде int i = foo () или float f = foo (), он бы знал, какой из них, но если оператор - это просто функция, о которой компилятор не узнает. Я это знаю. Спасибо.
nunos

7
@nunos, даже если бы это было float f = foo (), компилятор не смог бы это понять, потому что оба int были бы допустимыми входными данными для float. Сравните float f = 7; (7 - число с плавающей запятой или
целое

5
@NomeN Но ваше утверждение предполагает, что func (int i) и func (float i) были бы неразличимы для компилятора - и все мы знаем, что это не так. Настоящая причина указана Одедом (см. Следующий ответ) - дело в сигнатуре метода. И, кстати. 7 определенно является целым числом, а 7.0 или 7f - плавающим ;-)
Ta Sas

7
7.0 нет float, это double.
fredoverflow

3
Тот факт, что foo();без возвращаемого типа был бы неоднозначным, не обязательно является причиной запретить его как перегрузку. Есть аргументы, которые могут вызвать двусмысленность (например foo(null);), но это не делает перегрузку недействительной по своей сути.
shmosel 05

48

Причина в том, что перегрузки в Java разрешены только для методов с разными сигнатурами .

Тип возвращаемого значения не является частью сигнатуры метода, поэтому его нельзя использовать для распознавания перегрузок.

См. Определение методов из руководств по Java.


4
Но почему возвращаемый тип не является частью подписи
andho

51
ой "просто потому что"! Понимаю.
andho

3
Тип возврата ЯВЛЯЕТСЯ частью сигнатуры метода. Просто посмотрите на дизассемблирование класса.
konmik 06

2
На самом деле это не @konmik - не по правилам перегрузки метода. Попытайся. Одно и то же имя метода, одинаковые типы параметров в одном порядке, разные типы возвращаемых значений. Не компилируется.
Oded

3
Да, потому что возвращаемый тип не является частью подписи . Подпись - имя метода + типы и порядок его параметра. Прочтите ссылку, которую я предоставил в своем ответе: «Сигнатура объявленного выше метода: calculateAnswer(double, int, double, double)». Убедитесь, что возвращаемый тип не включен, @konmik.
Oded

22

До версии Java 5.0 при переопределении метода и параметры, и тип возвращаемого значения должны точно совпадать. В Java 5.0 он представляет новое средство, называемое ковариантным возвращаемым типом. Вы можете переопределить метод с той же сигнатурой, но вернуть подкласс возвращенного объекта. Другими словами, метод в подклассе может возвращать объект, тип которого является подклассом типа, возвращенного методом с той же сигнатурой в суперклассе.


3
Я был сбит с толку, когда впервые увидел это. Спасибо, что объяснили, почему это возможно!
Дилан Ноулз

2
перегрузка и переопределение разные. Перегрузка не обязательно (обязательно) предполагает наследование,
сэнсэйу

3
Этот ответ может показаться вводящим в заблуждение новичка в Java, потому что он вообще не имеет отношения к перегрузке , он переопределяет - совсем другое.
azizbekian 02

4

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

Ознакомьтесь с образцом кода.

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

}

в основном возвращаемый тип не принимается во внимание, только аргументы, грустно, но верно
Александр Миллс

1

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


1

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

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


0

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

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

Ошибка времени компиляции лучше, чем ошибка времени выполнения. Итак, компилятор java отображает ошибку времени компилятора, если вы объявляете тот же метод с такими же параметрами.


Чем это отличается от принятого ответа? (Причина, по которой это ошибка времени компиляции, состоит в том, что компилятор не может определить, какой метод вызывать, поэтому как он должен генерировать правильный исполняемый код)
UnholySheep

-2

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.