Могут ли переопределенные методы иметь разные возвращаемые типы ?
java
methods
overriding
santidoo
источник
источник
error: method() in subclass cannot override method() in superclass
Ответы:
Java поддерживает * ковариантные возвращаемые типы для переопределенных методов. Это означает, что у переопределенного метода может быть более конкретный тип возврата. То есть, пока новый тип возвращаемого значения может быть назначен типу возвращаемого значения метода, который вы переопределяете, это разрешено.
Например:
Это указано в разделе 8.4.5 Спецификации языка Java :
(«| R2 |» относится к стиранию R2, как определено в §4.6 JLS .)
* До Java 5 в Java были инвариантные возвращаемые типы, что означало, что тип возвращаемого значения переопределения метода должен точно соответствовать переопределяемому методу.
источник
Да, это может отличаться, но есть некоторые ограничения.
До версии Java 5.0, когда вы переопределяете метод, оба параметра и тип возвращаемого значения должны точно совпадать. В Java 5.0 он представляет новое средство, называемое ковариантным возвращаемым типом. Вы можете переопределить метод с той же сигнатурой, но вернуть подкласс возвращаемого объекта. Другими словами, метод в подклассе может возвращать объект, тип которого является подклассом типа, возвращаемого методом с той же сигнатурой в суперклассе.
источник
Да, если они вернут подтип. Вот пример:
Этот код компилируется и запускается.
источник
Вообще говоря, да, тип возврата метода переопределения может быть другим. Но это не так просто, так как в этом есть несколько случаев.
Случай 1: Если возвращаемый тип является примитивным типом данных или пустым.
Вывод: если тип возвращаемого значения недействителен или примитивен, тогда тип данных метода родительского класса и метода переопределения должен быть одинаковым. например, если тип возвращаемого значения - int, float, string, тогда он должен быть таким же
Случай 2: Если возвращаемый тип является производным типом данных:
Выходные данные: если тип возвращаемого значения метода родительского класса является производным типом, тогда тип возвращаемого значения метода переопределения является тем же производным типом данных подкласса, что и производный тип данных. например, предположим, что у меня есть класс A, B - подкласс A, C - подкласс B, а D - подкласс C; тогда, если суперкласс возвращает тип A, тогда метод переопределения подкласса может возвращать тип A, B, C или D, то есть его подтипы. Это также называется ковариацией.
источник
да Возможно .. тип возвращаемого значения может быть другим, только если тип возвращаемого значения метода родительского класса является
супертипом типа возвращаемого значения метода дочернего класса ..
означает
Если это так, то может быть разрешен другой тип возврата ...
источник
ну да ... И НЕТ.
зависит от вопроса. все здесь ответили относительно Java> = 5, а некоторые упомянули, что Java <5 не поддерживает ковариантные возвращаемые типы.
на самом деле спецификация языка Java> = 5 поддерживает его, а среда выполнения Java - нет. в частности, JVM не была обновлена для поддержки ковариантных возвращаемых типов.
в то время, что тогда рассматривалось как «умный» ход, но в итоге оказалось одним из худших проектных решений в истории Java, в Java 5 реализован ряд новых языковых функций без изменения JVM или спецификации файлов классов. вместо этого все функции были реализованы с помощью обмана в javac: компилятор генерирует / использует простые классы для вложенных / внутренних классов, стирание типов и приведение типов для дженериков, синтетические аксессоры для вложенных / внутренних классов частной "дружбы", синтетические поля экземпляров для внешнего 'this' указатели, синтетические статические поля для литералов '.class' и т. д. и т. д.
а ковариантные возвращаемые типы - это еще один синтаксический сахар, добавленный javac.
например, при компиляции:
javac выведет два метода get в классе Derived:
сгенерированный метод моста (помеченный
synthetic
иbridge
в байт-коде) - это то, что фактически переопределяет,Object:Base:get()
потому что для JVM методы с разными типами возврата полностью независимы и не могут переопределять друг друга. чтобы обеспечить ожидаемое поведение, мост просто вызывает ваш «настоящий» метод. в приведенном выше примере javac будет аннотировать как мостовые, так и реальные методы в Derived с помощью @SomeAnnotation.обратите внимание, что вы не можете вручную запрограммировать это решение на Java <5, потому что мост и реальные методы различаются только типом возвращаемого значения и, следовательно, они не могут сосуществовать в программе Java. но в мире JVM возвращаемые типы методов являются частью сигнатуры метода (точно так же, как их аргументы), и поэтому два метода, названные одинаково и принимающие одни и те же аргументы, тем не менее рассматриваются JVM как полностью независимые из-за их различных возвращаемых типов, и могут сосуществовать.
(Кстати, типы полей аналогичным образом являются частью подписи поля в байт-коде, поэтому допустимо иметь несколько полей разных типов, но с одинаковыми именами в одном классе байт-кода.)
поэтому, чтобы полностью ответить на ваш вопрос: JVM не поддерживает ковариантные типы возврата, но javac> = 5 имитирует его во время компиляции с покрытием сладкого синтаксического сахара.
источник
Типы переопределения и возврата и ковариантные возвращаемые значения,
подкласс должен определять метод, который точно соответствует унаследованной версии. Или, начиная с Java 5, вам разрешено изменять тип возвращаемого значения в
образец кода
Java 5, этот код будет компилироваться. Если вы попытаетесь скомпилировать этот код с помощью компилятора 1.4, скажет, что вы пытаетесь использовать несовместимый тип возвращаемого значения - sandeep1987 1 минуту назад
источник
Все остальные ответы верны, но, что удивительно, здесь не учитывается теоретический аспект: типы возвращаемых данных могут быть разными, но они могут ограничивать только тип, используемый в суперклассе, из-за принципа подстановки Лискова .
Это очень просто: когда у вас есть «клиентский» код, который вызывает какой-то метод:
тогда вышеуказанное должно работать (и возвращать что-то,
int
независимо от того, какая реализация былаbar()
вызвана).Значение: если есть подкласс Bar, который переопределяет,
bar()
вам все равно нужно вернуть что-то, что не нарушает «код вызывающего абонента».Другими словами: предположим, что база
bar()
должна возвращать int. Тогда подкласс может вернутьсяshort
- но неlong
потому, что вызывающие будут иметь дело соshort
значением, но не сlong
!источник
Тип возвращаемого значения должен быть таким же, как тип возвращаемого значения, объявленным в исходном переопределенном методе в суперклассе, или являться его подтипом.
источник
ДА, это возможно
источник
Да. Переопределенные методы могут иметь другой тип возвращаемого значения.
Но ограничения заключаются в том, что переопределенный метод должен иметь тип возвращаемого значения, который является более конкретным типом возвращаемого типа фактического метода.
Во всех ответах приведены примеры переопределенного метода, чтобы иметь возвращаемый тип, который является подклассом возвращаемого типа фактического метода.
Например :
Но это не ограничивается только подклассом. Даже классы, реализующие интерфейс, являются конкретным типом интерфейса и, таким образом, могут быть возвращаемым типом, в котором ожидается интерфейс.
Например :
источник
источник