IT박스

재정의 된 메소드가 리턴 유형이 다를 수 있습니까?

itboxs 2020. 7. 7. 07:57
반응형

재정의 된 메소드가 리턴 유형이 다를 수 있습니까?


재정의 된 메소드가 다른 리턴 유형을 가질 수 있습니까 ?


Java는 재정의 된 메소드에 대해 * 공변량 리턴 유형을 지원 합니다. 이는 재정의 된 메소드가 보다 구체적인 리턴 유형을 가질 수 있음을 의미합니다 . 즉, 새 리턴 유형이 대체하는 메소드의 리턴 유형에 지정 가능한 한 허용됩니다.

예를 들면 다음과 같습니다.

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

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

이것은 Java Language Specification의 섹션 8.4.5에 지정되어 있습니다 .

리턴 유형이 참조 유형 인 경우 리턴 유형은 서로 대체하는 메소드마다 다를 수 있습니다. return-type-substitutability의 개념은 공변량 리턴, 즉 리턴 유형을 하위 유형으로 특수화하는 것을 지원합니다.

리턴 유형이 R1 인 메소드 선언 d1은 다음 조건이 충족되는 경우에만 리턴 유형이 R2 인 다른 메소드 d2에 대해 리턴 유형 대체 가능합니다.

  • R1이 void이면 R2가 void입니다.

  • R1이 기본 유형 인 경우 R2는 R1과 동일합니다.

  • R1이 참조 유형 인 경우 :

    • R1은 R2의 하위 유형이거나 R1은 확인되지 않은 변환 (§5.1.9)에 의해 R2의 하위 유형으로 변환 될 수 있습니다. 또는

    • R1 = | R2 |

( "| R2 |"는 JLS의 §4.6에 정의 된대로 R2의 삭제를 나타냅니다 .)


* Java 5 이전에는 Java가 변하지 않는 리턴 유형을 가지고 있었으므로 이는 대체되는 메소드와 정확하게 일치하는 데 필요한 메소드 대체의 리턴 유형을 의미했습니다.


예, 다를 수 있지만 몇 가지 제한 사항이 있습니다.

Java 5.0 이전에는 메소드를 대체 할 때 매개 변수와 리턴 유형이 모두 정확히 일치해야합니다. Java 5.0에서는 공변량 리턴 유형이라는 새로운 기능이 도입되었습니다. 동일한 서명으로 메소드를 대체 할 수 있지만 리턴 된 오브젝트의 서브 클래스를 리턴합니다. 즉, 서브 클래스의 메소드는 유형이 수퍼 클래스에서 동일한 서명으로 메소드가 리턴 한 유형의 서브 클래스 인 오브젝트를 리턴 할 수 있습니다.


예, 하위 유형을 반환하면 가능합니다. 예를 들면 다음과 같습니다.

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 {
    }
}

이 코드는 컴파일되고 실행됩니다.


대체로 예 반환 유형의 재정의 방법이 다를 수 있습니다. 그러나 이것과 관련이있는 경우는 간단하지 않습니다.

사례 1 : 반환 유형이 기본 데이터 유형이거나 void 인 경우

Output: If the return type is void or primitive then the data type of parent class method and overriding method should be same. e.g. if return type is int, float, string then it should be same

Case 2: If the return type is derived data type:

Output: If the return type of the parent class method is derived type then the return type of the overriding method is same derived data type of sub class to the derived data type. e.g. Suppose i have a class A B is subclass to A C is subclass to B D is subclass to C then if if the super class is returning type A then the overriding method is subclass can return A, B, C or D type i.e its sub types. This is also called as covarience.


yes It is possible.. returns type can be different only if parent class method return type is
a super type of child class method return type..
means

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

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

Class Circle {

}

class Square extends Circle {

}


이것이 다른 반환 유형이면 허용 될 수 있습니다 ...


반환 유형은 수퍼 클래스의 원래 재정의 된 메소드에 선언 된 반환 유형과 동일하거나 하위 유형이어야합니다.


재정의 및 반환 유형 및 공변량 반환
하위 클래스는 상속 된 버전과 정확히 일치하는 메서드를 정의해야합니다. 또는 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 분 전


The other answers are all correct, but surprisingly all leaving out the theoretical aspect here: return types can be different, but they can only restrict the type used in the super class because of the Liskov Substitution Principle.

It is super simple: when you have "client" code that calls some method:

int foo = someBar.bar();

then the above has to work (and return something that is an int no matter which implementation of bar() is invoked).

Meaning: if there is a Bar subclass that overrides bar() then you still have to return something that doesn't break "caller code".

In other words: assume that the base bar() is supposed to return int. Then a subclass could return short - but not long because callers will be fine dealing with a short value, but not a long!


well, the answer is yes... AND NO.

depends on the question. everybody here answered regarding Java >= 5, and some mentioned that Java < 5 does not feature covariant return types.

actually, the Java language spec >= 5 supports it, but the Java runtime does not. in particular, the JVM was not updated to support covariant return types.

in what was seen then as a "clever" move but ended up being one of the worst design decisions in Java's history, Java 5 implemented a bunch of new language features without modifying the JVM or the classfile spec at all. instead all features were implemented with trickery in javac: the compiler generates/uses plain classes for nested/inner classes, type erasure and casts for generics, synthetic accessors for nested/inner class private "friendship", synthetic instance fields for outer 'this' pointers, synthetic static fields for '.class' literals, etc, etc.

and covariant return types is yet more syntactic sugar added by javac.

for example, when compiling this:

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

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

javac will output two get methods in the Derived class:

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

the generated bridge method (marked synthetic and bridge in bytecode) is what actually overrides Object:Base:get() because, to the JVM, methods with different return types are completely independent and cannot override each other. to provide the expected behavior, the bridge simply calls your "real" method. in the example above, javac will annotate both bridge and real methods in Derived with @SomeAnnotation.

note that you cannot hand-code this solution in Java < 5, because bridge and real methods only differ in return type and thus they cannot coexist in a Java program. but in the JVM world, method return types are part of the method signature (just like their arguments) and so the two methods named the same and taking the same arguments are nonetheless seen as completely independent by the JVM due to their differing return types, and can coexist.

(BTW, the types of fields are similarly part of the field signature in bytecode, so it is legal to have several fields of different types but named the same within a single bytecode class.)

so to answer your question fully: the JVM does not support covariant return types, but javac >= 5 fakes it at compile time with a coating of sweet syntactic sugar.


YES it can be possible

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

Yes. It is possible for overridden methods to have different return type .

But the limitations are that the overridden method must have a return type that is more specific type of the return type of the actual method.

All the answers have given examples of the overridden method to have a return type which is a subclass of the return type of the actual method.

For example :

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         
  }

}

But this is not only limited to subclass.Even classes that implement an interface are a specific type of the interface and thus can be a return type where the interface is expected.

For example :

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         
  }

}

Yes we can have! Covariant return type is one of the common example

참고URL : https://stackoverflow.com/questions/14694852/can-overridden-methods-differ-in-return-type

반응형