Подтвердить что ты не робот

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

Могут ли переопределенные методы иметь разные типы возвращаемых данных?

4b9b3361

Ответ 1

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

Например:

class ShapeBuilder {
    ...
    public Shape build() {
    ....
}

class CircleBuilder extends ShapeBuilder{
    ...
    @Override
    public Circle build() {
    ....
}

Это указано в разделе 8.4.5 Спецификации языка Java:

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

Объявление метода d1 с типом возврата R1 является заменяемым типом возврата для другого метода d2 с типом возврата R2, если и только если выполняются следующие условия:

  • Если R1 является недействительным, то R2 является недействительным.

  • Если R1 является примитивным типом, то R2 идентичен R1.

  • Если R1 является ссылочным типом, тогда:

    • R1 является либо подтипом R2, либо R1 может быть преобразован в подтип R2 путем неконтролируемого преобразования (§5.1.9), или

    • R1 = | R2 |

("| R2 |" относится к стиранию R2, как определено в §4.6 JLS.)


* До Java 5 у Java были инвариантные возвращаемые типы, что означало возвращаемый тип переопределения метода, необходимого для точного соответствия переопределяемого метода.

Ответ 2

Да, это может различаться, но их некоторые ограничения.

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

Ответ 3

Да, если они возвращают подтип. Вот пример:

package com.sandbox;

public class Sandbox {

    private static class Parent {
        public ParentReturnType run() {
            return new ParentReturnType();
        }
    }

    private static class ParentReturnType {

    }

    private static class Child extends Parent {
        @Override
        public ChildReturnType run() {
            return new ChildReturnType();
        }
    }

    private static class ChildReturnType extends ParentReturnType {
    }
}

Этот код компилируется и запускается.

Ответ 4

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

Случай 1: если тип возврата является примитивным типом данных или void.

Выход: если тип возврата недействителен или примитивен, тогда тип данных метода родительского класса и метода переопределения должен быть таким же. например если тип возврата - int, float, string, то он должен быть таким же

Случай 2: Если тип возвращаемого типа является производным типом данных:

Вывод: если тип возвращаемого значения метода родительского класса является производным типом, то возвращаемый тип метода переопределения - это один и тот же производный тип данных подкласса для производного типа данных. например Предположим, что у меня есть класс А    B является подклассом A    C - подкласс к B    D является подклассом C    то если, если суперкласс возвращает тип A, то переопределяющим методом является подкласс, который может возвращать типы A, B, C или D i.e его подтипы. Это также называется ковариацией.

Ответ 5

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

class ParentClass {
    public Circle() method1() {
        return new Cirlce();
    }
}

class ChildClass extends ParentClass {
    public Square method1() {
        return new Square();
    }
}

Class Circle {

}

class Square extends Circle {

}


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

Ответ 6

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

Ответ 7

Типы переопределения и возврата, а также ковариантные значения
подкласс должен точно определить метод, который соответствует унаследованной версии. Или, с точки зрения Java 5, вам разрешено изменять тип возврата в

пример кода


                                                                                                            class Alpha {
          Alpha doStuff(char c) {
                  return new Alpha();
              }
           }
             class Beta extends Alpha {
                    Beta doStuff(char c) { // legal override in Java 1.5
                    return new Beta();
                    }
             } } 
Начиная с Java 5, этот код будет скомпилирован. Если вы попытаетесь скомпилировать этот код с компилятором 1.4, скажете, что пытаетесь использовать несовместимый тип возврата - sandeep1987 1 мин. Назад

Ответ 8

ДА это может быть возможно

class base {

 base show(){

System.out.println("base class");

return new base();

}
}

class sub extends base{

sub show(){

    System.out.println("sub class");

    return new sub();

 }
}

class inheritance{

 public static void main(String []args) {

        sub obj=new sub();

            obj.show();
 }
}

Ответ 9

Все остальные ответы верны, но, что удивительно, все они не учитывают теоретический аспект: типы возвращаемых данных могут быть разными, но они могут ограничивать только тип, используемый в суперклассе, из-за принципа подстановки Лискова.

Это очень просто: когда у вас есть "клиентский" код, который вызывает некоторый метод:

int foo = someBar.bar();

тогда вышеупомянутое должно работать (и возвращать что-то, что является int независимо от того, какая реализация bar() вызывается).

Значение: если есть подкласс Bar, который переопределяет bar() вам все равно придется возвращать то, что не нарушает "код вызывающего абонента".

Другими словами: предположим, что base bar() должна возвращать int. Тогда подкласс может вернуть short - но не long потому что вызывающим будет хорошо иметь дело с short значением, но не с long !

Ответ 10

Да. Переопределенные методы могут иметь другой тип возвращаемого значения.

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

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

Например:

public class Foo{

   //method which returns Foo
  Foo getFoo(){
      //your code         
  }

}

 public class subFoo extends Foo{

  //Overridden method which returns subclass of Foo
  @Override
  subFoo getFoo(){
      //your code         
  }

}

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

Например:

public interface Foo{

   //method which returns Foo
  Foo getFoo();

}

 public class Fizz implements Foo{

  //Overridden method which returns Fizz(as it implements Foo)
  @Override
  Fizz getFoo(){
      //your code         
  }

}

Ответ 11

Да, мы можем иметь! Ковариантный тип возврата является одним из распространенных примеров

Ответ 12

хорошо, ответ да... И НЕТ.

зависит от вопроса. все здесь ответили относительно Java> = 5, а некоторые упоминали, что Java <5 не поддерживает ковариантные типы возврата.

на самом деле спецификация языка Java> = 5 поддерживает его, а среда выполнения Java - нет. в частности, JVM не была обновлена для поддержки ковариантных типов возврата.

то, что тогда считалось "умным" шагом, но в итоге оказалось одним из худших проектных решений в истории Java, в Java 5 реализовано множество новых языковых функций без каких-либо изменений спецификации JVM или файла классов. вместо этого все функции были реализованы с помощью хитрости в javac: компилятор генерирует/использует простые классы для вложенных/внутренних классов, стирание типов и приведение к обобщенным типам, синтетические средства доступа для закрытых/дружных вложенных/внутренних классов, синтетические поля экземпляра для внешнего 'this' указатели, синтетические статические поля для литералов .class и т.д. и т.д.

а ковариантные типы возвращаемых данных - это еще более синтаксический сахар, добавленный javac.

например, при компиляции этого:

class Base {
  Object get() { return null; }
}

class Derived extends Base {
  @Override
  @SomeAnnotation
  Integer get() { return null; }
}

javac выведет два метода get в классе Derived:

Integer Integer:Derived:get() { return null; }
synthetic bridge Object Object:Derived:get() { return Integer:Derived:get(); }

сгенерированный метод моста (помеченный как synthetic и bridge в байт-коде) - это то, что на самом деле переопределяет Object:Base:get() поскольку для JVM методы с различными типами возвращаемых данных полностью независимы и не могут переопределять друг друга. чтобы обеспечить ожидаемое поведение, мост просто вызывает ваш "настоящий" метод. в приведенном выше примере javac будет аннотировать как мостовые, так и реальные методы в Derived с помощью @SomeAnnotation.

обратите внимание, что вы не можете вручную закодировать это решение в Java <5, потому что мостовые и реальные методы различаются только по типу возвращаемого значения и, следовательно, они не могут сосуществовать в Java-программе. но в мире JVM типы возврата методов являются частью сигнатуры метода (так же, как их аргументы), и поэтому два метода, названные одинаково и принимающие одинаковые аргументы, тем не менее рассматриваются JVM как полностью независимые из-за их различных типов возврата, и может сосуществовать.

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

Итак, чтобы полностью ответить на ваш вопрос: JVM не поддерживает ковариантные типы возврата, но javac> = 5 подделывает его во время компиляции с покрытием из сладкого синтаксического сахара.