공변 반환 유형이란 무엇입니까?


105

Java의 공변 반환 유형은 무엇입니까? 일반적으로 객체 지향 프로그래밍에서?


5
이 블로그 게시물 ( blogs.oracle.com/sundararajan/entry/… )은 여기에서 지식 기반에 추가하는 것만으로 설명합니다.
Akhil Jain 2013

@AkhilJain : 그 블로그 게시물은 훌륭하고 간단합니다. Java가 공변 반환 유형을 지원하는 방법에 대해 내가 본 것 중 가장 좋은 설명입니다.
kevinarpe

@kevinarpe 감사합니다, 많은 사람들에게 도움이되어 기쁩니다.
아킬 자이나교

답변:


143

공변 반환은 메서드를 재정의 할 때 재정의 된 메서드의 반환 유형이 재정의 된 메서드의 반환 유형의 하위 유형이 될 수 있음을 의미합니다.

예제를 통해이를 명확히하기 위해 일반적인 경우는 Object.clone()-형식을 반환하도록 선언됩니다 Object. 다음과 같이 자신의 클래스에서이를 재정의 할 수 있습니다.

public class MyFoo
{

   ...

   // Note covariant return here, method does not just return Object
   public MyFoo clone()
   {
       // Implementation
   }
}

여기서 이점은 MyFoo 객체에 대한 명시 적 참조를 보유하는 모든 메서드가 clone()반환 값이의 인스턴스임을 (캐스팅하지 않고) 호출 하고 알 수 있다는 것 입니다 MyFoo. 공변 반환 유형이 없으면 MyFoo의 재정의 된 메서드가 반환되도록 선언해야합니다. Object따라서 호출 코드는 메서드 호출의 결과를 명시 적으로 다운 캐스트해야합니다 (양측이 "알고"있다고 ​​생각하더라도 항상 MyFoo의 인스턴스 일 수 있다고 생각). ).

특별한 것은 없으며 clone()재정의 된 메서드는 공변 반환을 가질 수 있습니다. 여기서는 이것이 종종 유용한 표준 메서드이기 때문에 예제로 사용했습니다.


이와 관련이있는 것으로 생각되지 List<Foo>List<FooBar> ?
zinking

2
이것은 여기에서 요청한 공변 반환 유형이 아니라 더 넓은 의미에서 공변 유형입니다 . 하지만 기본 원칙은 동일합니다. 최상위 수준 정의를 clone()으로 생각 Method<Void, Object>하고 더 구체적인 항목 Method<Void, MyFoo>을 해당 상위 유형에 할당 할 수 있는지 물어볼 수 있습니다. Java 메소드가 반환 유형에서 공변하는 경우에만 그렇습니다.
Andrzej Doyle

38

다음은 또 다른 간단한 예입니다.

Animal 수업

public class Animal {

    protected Food seekFood() {

        return new Food();
    }
}

Dog 수업

public class Dog extends Animal {

    @Override
    protected Food seekFood() {

        return new DogFood();
    }
}

아래와 같이 DogseekFood()메서드 의 반환 유형 을 DogFood-의 하위 클래스 로 수정할 수 Food있습니다.

@Override
protected DogFood seekFood() {

    return new DogFood();
}

그것은 완벽하게 합법적 인 재정의이며 DogseekFood()메서드 의 반환 유형은 공변 반환 유형으로 알려져 있습니다.


8

JDK 1.5 릴리스부터 공변 유형이 Java에 도입되었습니다. 간단한 사례로 설명 하겠습니다. 함수를 재정의하면 함수가 동작을 변경할 수 있습니다. 대부분의 책에서 읽을 수있는 을 변경할 수 있지만 {저자}가 놓친 부분은 반환 유형도 변경할 수 있다는 것입니다. 아래 링크를 확인하여 메서드의 기본 버전 반환 유형에 할당 할 수있는 한 반환 유형을 변경할 수 있습니다.

따라서 파생 된 형식을 반환하는이 기능을 COVARIANT라고합니다.

재정의 된 메서드는 반환 유형이 다를 수 있습니까?


7

공변 반환 유형은 단순히 자신의 클래스 참조 또는 하위 클래스 참조를 반환하는 것을 의미합니다.

class Parent {
 //it contain data member and data method
}

class Child extends Parent { 
//it contain data member and data method
 //covariant return
  public Parent methodName() {
     return new Parent();
          or 
     return Child();
  }

}

1
또한 케이스 포함 Parent.foo()다시 표시 무관 유형 AChild.foo()반환 일종 B으로부터 유도를 A.
Davis Herring

2

위의 답변에 추가하려면 재정의 메서드 (서브 클래스 메서드)의 반환 유형이 재정의 된 메서드 (슈퍼 클래스 메서드)의 반환 유형의 하위 클래스 여야한다는 제약 조건으로 공변 반환 유형간에 재정의가 가능합니다. 이것은 Java 5부터 유효합니다.


1

공변 반환 유형은 반환 유형이 하위 클래스와 동일한 방향으로 다를 수 있음을 지정합니다.

class One{  
    One get(){return this;}  
}  

class Two extends One{  
  Two get(){return this;}  

void message(){
  System.out.println("After Java5 welcome to covariant return type");
}  

public static void main(String args[]){  
    new Two().get().message();  
}  
}

Java 5 이전에는 반환 유형을 변경하여 메서드를 재정의 할 수 없었습니다. 하지만 지금은 Java5 이후로

서브 클래스가 리턴 유형이 Non-Primitive 인 메소드를 대체하지만 리턴 유형을 서브 클래스 유형으로 변경하는 경우 리턴 유형을 변경하여 메소드를 대체 할 수 있습니다.


1
  • 이는 클래스 계층 구조에 존재하는 혼동 유형 캐스트를 방지하여 코드를 읽기 쉽고, 사용 가능하며, 유지 관리 할 수 ​​있도록합니다.

  • 메서드를 재정의 할 때 더 구체적인 반환 유형을 가질 수 있습니다 .

  • 반환시 런타임 ClassCastExceptions 방지에 대한 도움말

참조 : www.geeksforgeeks.org


0
  • Java의 공변 반환 유형을 사용하면 재정의 된 메서드의 반환 유형을 좁힐 수 있습니다.
  • 이 기능은 클라이언트 측에서 다운 캐스팅을 방지하는 데 도움이됩니다. 프로그래머가 유형 검사 및 다운 캐스팅없이 프로그래밍 할 수 있습니다.
  • 공변 반환 유형은 항상 기본이 아닌 반환 유형에 대해서만 작동합니다.
interface Interviewer {
    default Object submitInterviewStatus() {
        System.out.println("Interviewer:Accept");
        return "Interviewer:Accept";
    }
}
class Manager implements Interviewer {
    @Override
    public String submitInterviewStatus() {
        System.out.println("Manager:Accept");
        return "Manager:Accept";
    }
}
class Project {
    public static void main(String args[]) {
        Interviewer interviewer = new Manager();
        interviewer.submitInterviewStatus();
        Manager mgr = new Manager();
        mgr.submitInterviewStatus();
    }
}

다른 예는 Java입니다.

UnaryOperator.java

@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {

    /**
     * Returns a unary operator that always returns its input argument.
     *
     * @param <T> the type of the input and output of the operator
     * @return a unary operator that always returns its input argument
     */
    static <T> UnaryOperator<T> identity() {
        return t -> t;
    }
}

Function.java

@FunctionalInterface
public interface Function<T, R> {

    ........
    ........
    ........
    ........

    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

0

Java5 이전에는 반환 유형을 변경하여 메서드를 재정의 할 수 없었습니다. 그러나 이제 Java5부터는 서브 클래스가 리턴 유형이 Non-Primitive 인 메소드를 대체하지만 리턴 유형을 서브 클래스 유형으로 변경하면 리턴 유형을 변경하여 메소드를 대체 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.