Почему перегрузка метода не определяется для различных типов возврата?

  1. Всегда создают резервную копию перед изменением.
  2. Всегда делают модификации (например, ALTER TABLE) с помощью сценария.
  3. Всегда изменяют данные (например, УДАЛИТЕ) с помощью хранимой процедуры.
9
задан gnuvince 17 October 2009 в 16:44
поделиться

5 ответов

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

def foo(s: String) : String = s + "Hello"
def foo(i: Int) : Int = i + 1

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

Однако подумайте, как разрешение такой перегрузки может работать в тандеме с подтипом:

class A {
  def foo: Int = 1
}
val a: A = //...lookup an A
val b = a.foo

Это, конечно, вполне допустимый код, и javac однозначно разрешит вызов метода. Но что, если я создаю подкласс A следующим образом:

class B extends A {
  def foo: String = "Hello"
}

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

6
ответ дан 4 December 2019 в 08:52
поделиться

На самом деле, вы можете заставить его работать с помощью магии «неявного». Как показано ниже:

scala> case class Result(i: Int,s: String)

scala> class C {
     |     def m: Result = Result(42,"forty two")
     | }

scala> implicit def res2int(res: Result) = res.i

scala> implicit def res2str(res: Result) = res.s

scala> val c = new C

scala> val i: Int = c.m

i: Int = 42


scala> val s: String = c.m

s: String = forty two

scala>
8
ответ дан 4 December 2019 в 08:52
поделиться

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

Допустим, у вас есть два метода, подписи которых отличаются только возвращаемый тип.

Если вы вызываете этот метод, как компилятор (интерпретатор?) узнает, какой метод вы на самом деле хотите вызвать?

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

Java не допускает перегрузки возвращаемых типов, и, поскольку scala построен на java JVM, это, вероятно, просто ограничение java.

(Edit) Обратите внимание, что ковариантная доходность - это другая проблема. При переопределении метода вы можете выбрать возврат подкласса класса, который должен возвращать, но не можете выбрать для возврата несвязанный класс.

2
ответ дан 4 December 2019 в 08:52
поделиться

Основная причина заключается в проблемах сложности: при «нормальном» подходе компилятора вы идете наизнанку (от внутреннего выражения к внешней области видимости), строя свой двоичный файл шаг за шагом; если вы добавляете дифференциацию только по возвращаемому типу, вам необходимо перейти на подход с возвратом, что значительно увеличивает время компиляции, сложность компилятора (= ошибки!).

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

Не стоит беспокоиться.

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

6
ответ дан 4 December 2019 в 08:52
поделиться

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

Scala - это язык, ориентированный на выражения (каждый оператор является выражением). Обычно языки, ориентированные на выражения, предпочитают, чтобы семантика выражений зависела только от оценки области действия, а не от того, что происходит с результатом, поэтому для выражения foo () в i_take_an_int (foo ( )) и i_take_any_type (foo ()) и foo () в качестве оператора все вызывают одну и ту же версию foo () .

Там '

1
ответ дан 4 December 2019 в 08:52
поделиться