Почему возвращаемый тип метода не включен в подпись?
Пример
public void method1(String arg){...}
public String method1(String arg){...}
Это приведет к ошибке.
Почему возвращаемый тип метода не включен в подпись?
Пример
public void method1(String arg){...}
public String method1(String arg){...}
Это приведет к ошибке.
Это сделано потому, что компилятор не сможет определить перегрузку во всех контекстах all contexts.
Например, если вы позвоните
String x = method1("aaa");
компилятор знает, что вы ищете вторую перегрузку. Тем не менее, если вы позвоните
method1("aaa");
таким образом, компилятор не знает, какой из двух методов вы хотите вызвать, потому что можно вызывать метод, возвращающий String
, и отбрасывать результат. Чтобы избежать двусмысленностей, подобных этой, Java запрещает перегрузки, которые зависят только от типа возвращаемого значения.
Поскольку ваш вопрос не затрагивает какой-либо конкретный язык программирования в названии (я знаю, что это делается в теге), я расскажу о своем недавнем опыте работы с Swift. В Swift функция/подпись метода фактически включает тип возврата. Поэтому компилятор выдает ошибку только в том случае, если вы вызываете эту функцию/метод без явного указания типа возврата, например:
func some() -> Bool {
return true;
}
func some() -> Int {
return 1;
}
let valBool: Bool = some()
let valInt: Int = some()
// this doesn't work: Ambiguous use of 'some'
some()
В дополнение к этому Swift даже делает его более интересным. Это позволяет вам иметь 2 функции/методы с одинаковыми параметрами и типами возврата только в том случае, если имена параметров различны, например:
func some(#foo: Bool) -> Bool {
return foo;
}
func some(#bar: Bool) -> Bool {
return bar;
}
some(foo: true)
some(bar: false)
Таким образом, это дает вам семантическую дифференциацию в подписи методов
UPD. Поскольку имя внешнего параметра Swift 2.0 было изменено, и теперь вы должны дважды указывать внешние и локальные имена, даже если это одно и то же
func some(foo foo: Bool) -> Bool {
return foo;
}
func some(bar bar: Bool) -> Bool {
return bar;
}
some(foo: true)
some(bar: false)
Вы не можете перегружать метод только возвращаемым типом. Это просто незаконно. Предположим на мгновение, что методы перегрузки с использованием типа возврата будут законными, и вы определили два метода method1
. Теперь мы хотим называть то, что возвращает String object
:
String string = method1(sth);
JVM теоретически сможет распознать, какой метод вы хотели бы назвать, но как насчет такого вызова:
method1(sth);
Как вы можете видеть, оба метода могут быть вызваны, и такие операции недвусмысленны. JVM не знает, какой метод он должен назвать. Вот почему такая перегрузка запрещена.
Поскольку невозможно решить, какой из перегруженных методов следует вызывать в таком случае:
public static void main(String... args) {
method1("aaa");
}
При проектировании таких вещей, как разрешение перегрузки, необходимо учитывать несколько моментов.
Причины отказа от перегрузки по типу возврата:
Причины добавления перегрузки по типу возврата:
int x = json.get("int_value"); float y = json.get("float_value");
int x = json.get("int_value"); float y = json.get("float_value");
? На некоторых языках (например, C++), которые все еще можно достичь с помощью прокси и операторов трансляции, но перегрузка по типу возврата будет намного проще.string s; getline(cin, s);
string s; getline(cin, s);
vs string s = getline(cin);
, И именно здесь выразительность сочетается с ссылочной прозрачностью и, в конечном счете, легкостью переваривания кода.Вернемся к вашему вопросу "почему?". Поскольку вы спрашивали о Java, ответ, очевидно, объясняется тем, что Джеймс ценил причины отказа от возвращаемых типов перегрузок по причинам, чтобы включить их в язык.
вы можете вызвать функцию как процедуру: method1("arg");
где method1 - второй метод в вашем списке (String method1(String arg){}
). Компилятор тогда не сможет отличить его от первого (void method1(String arg){}
).
Компилятор заботится о привязке метода. Когда он сталкивается с methodName(), он должен связываться с определением метода, в этот момент он может не знать тип возвращаемого метода. Таким образом, тип возвращаемого значения метода не включен в сигнатуру метода. Компилятор связывает метод в соответствии с сигнатурой метода.
Перегрузка метода проверяется на основе количества и типа аргументов, а не на основе типа возвращаемого значения. Вот почему вы получаете ошибку.