共変戻り値型とは何ですか?


105

Javaの共変戻り値型とは何ですか?一般にオブジェクト指向プログラミングでは?


5
このブログ投稿(blogs.oracle.com/sundararajan/entry/…)で説明し、ここにナレッジベースを追加します。
Akhil Jain 2013

@AkhilJain:そのブログ投稿は素晴らしくてシンプルです。これは、Javaが共変の戻り値の型をどのようにサポートするかについて、私が今まで見た中で最高の説明です。
kevinarpe 2016年

@kevinarpeおかげで、とても多くの人々に役立つことを嬉しく思います。
Akhil Jain

回答:


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>and と関係があるはずではないList<FooBar>ですか?
2016年

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

これは、の戻り値の型変更することが可能ですDogS」seekFood()へのメソッド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ます。
デイビスヘリング

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以来、

サブクラスが戻り値の型が非プリミティブであるメソッドをオーバーライドする場合、戻り値の型をサブクラス型に変更する場合、戻り値の型を変更することによってメソッドをオーバーライドすることが可能です。


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以降では、戻り値の型が非プリミティブであるメソッドをサブクラスがオーバーライドする場合、戻り値の型を変更することでメソッドをオーバーライドできますが、戻り値の型はサブクラス型に変更されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.