Was ist ein kovarianter Rückgabetyp?


105

Was ist ein kovarianter Rückgabetyp in Java? In der objektorientierten Programmierung im Allgemeinen?


5
In diesem Blog-Beitrag ( blogs.oracle.com/sundararajan/entry/… ) wird erklärt, was hier nur zur Wissensbasis beiträgt .
Akhil Jain

@AkhilJain: Dieser Blog-Beitrag ist brillant und einfach. Es ist die beste Erklärung am Beispiel, die ich je gesehen habe, wie Java kovariante Rückgabetypen unterstützt.
Kevinarpe

@ kevinarpe danke, ich bin froh, dass es für so viele Menschen hilfreich ist.
Akhil Jain

Antworten:


143

Kovariante Rückgabe bedeutet, dass beim Überschreiben einer Methode der Rückgabetyp der überschreibenden Methode ein Subtyp des Rückgabetyps der überschriebenen Methode sein darf.

Um dies anhand eines Beispiels zu verdeutlichen, ist ein häufiger Fall Object.clone()- der deklariert wird, einen Typ von zurückzugeben Object. Sie können dies in Ihrer eigenen Klasse wie folgt überschreiben:

public class MyFoo
{

   ...

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

Der Vorteil hierbei ist, dass jede Methode, die einen expliziten Verweis auf ein MyFoo-Objekt enthält, aufrufen clone()und (ohne Umwandlung) wissen kann, dass der Rückgabewert eine Instanz von istMyFoo . Ohne kovariante Rückgabetypen müsste die überschriebene Methode in MyFoo für die Rückgabe deklariert werden Object- und daher müsste das Aufrufen von Code das Ergebnis des Methodenaufrufs explizit herabsetzen (obwohl beide Seiten "wissen", dass es immer nur eine Instanz von MyFoo sein kann ).

Beachten Sie, dass es nichts Besonderes gibt clone()und dass jede überschriebene Methode eine kovariante Rückgabe haben kann. Ich habe sie hier als Beispiel verwendet, da es sich um eine Standardmethode handelt, bei der dies häufig nützlich ist.


soll es nicht mit List<Foo>und verwandt sein List<FooBar>?
Zinking

2
Das sind kovariante Typen im weiteren Sinne und nicht nur der kovariante Rückgabetyp , nach dem hier gefragt wird. Es ist jedoch dasselbe zugrunde liegende Prinzip - Sie können sich die Definition auf oberster Ebene clone()als a Method<Void, Object>vorstellen und fragen, ob das spezifischere Method<Void, MyFoo>diesem übergeordneten Typ zuweisbar ist. Was es ist, wenn und nur wenn Java-Methoden in ihrem Rückgabetyp kovariant sind.
Andrzej Doyle

38

Hier ist ein weiteres einfaches Beispiel:

Animal Klasse

public class Animal {

    protected Food seekFood() {

        return new Food();
    }
}

Dog Klasse

public class Dog extends Animal {

    @Override
    protected Food seekFood() {

        return new DogFood();
    }
}

Es ist möglich, den Rückgabetyp der Methode von Dog' seekFood()in DogFoodeine Unterklasse von zu ändern Food, wie unten gezeigt:

@Override
protected DogFood seekFood() {

    return new DogFood();
}

Das ist vollkommen gesetzlich zwingende, und der Rückgabetyp von Dog‚s - seekFood()Methode ist bekannt als kovariante Rückgabetyp .


8

Ab der Veröffentlichung von JDK 1.5 wurden kovariante Typen in Java eingeführt. und ich erkläre es Ihnen mit einem einfachen Fall: Wenn wir eine Funktion überschreiben, darf die Funktion ihr Verhalten ändern , das Sie in den meisten Büchern lesen können, aber was sie {Autoren} verpassen ist, dass wir auch den Rückgabetyp ändern können. Überprüfen Sie den folgenden Link, um zu verdeutlichen, dass wir den Rückgabetyp ändern können, solange er dem Rückgabetyp der Basisversion der Methode zugewiesen werden kann.

Diese Funktion zur Rückgabe abgeleiteter Typen heißt also COVARIANT ...

Können sich überschriebene Methoden im Rückgabetyp unterscheiden?


7

kovariante Rückgabetypen bedeuten einfach die Rückgabe einer eigenen Klassenreferenz oder ihrer untergeordneten Klassenreferenz.

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
Dies schließt auch den Fall ein, in dem Parent.foo()ein nicht verwandter Typ Aund Child.foo()ein Babgeleiteter Typ zurückgegeben werden A.
Davis Herring

2

Um die obigen Antworten zu ergänzen, ist das Überschreiben zwischen Rückgabetypen mit zwei Varianten möglich, mit der Einschränkung, dass der Rückgabetyp der überschreibenden Methode (Unterklassenmethode) eine Unterklasse des Rückgabetyps der überschriebenen Methode (Oberklassenmethode) sein sollte. Dies gilt ab Java 5.


1

Der kovariante Rückgabetyp gibt an, dass der Rückgabetyp in derselben Richtung wie die Unterklasse variieren kann

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

Vor Java 5 war es nicht möglich, eine Methode durch Ändern des Rückgabetyps zu überschreiben. Aber jetzt, seit Java5,

Es ist möglich, die Methode durch Ändern des Rückgabetyps zu überschreiben, wenn die Unterklasse eine Methode überschreibt, deren Rückgabetyp nicht primitiv ist, deren Rückgabetyp jedoch in den Unterklassentyp geändert wird.


1
  • Es hilft, verwirrende Typumwandlungen in der Klassenhierarchie zu vermeiden und so den Code lesbar, verwendbar und wartbar zu machen.
  • Wir haben die Freiheit, spezifischere Rückgabetypen zu haben, wenn
    Methoden überschrieben werden.

  • Hilfe bei der Verhinderung von ClassCastExceptions zur Laufzeit bei Rückgaben

Referenz: www.geeksforgeeks.org


0
  • Der kovariante Rückgabetyp in Java ermöglicht die Eingrenzung des Rückgabetyps der überschriebenen Methode.
  • Diese Funktion hilft dabei, ein Downcasting auf der Client-Seite zu vermeiden. Damit kann der Programmierer ohne Typprüfung und Downcasting programmieren.
  • Der kovariante Rückgabetyp funktioniert immer nur für nicht primitive Rückgabetypen.
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();
    }
}

Ein anderes Beispiel stammt aus 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

Vor Java5 war es nicht möglich, eine Methode durch Ändern des Rückgabetyps zu überschreiben. Seit Java5 ist es jedoch möglich, die Methode durch Ändern des Rückgabetyps zu überschreiben, wenn die Unterklasse eine Methode überschreibt, deren Rückgabetyp nicht primitiv ist, deren Rückgabetyp jedoch in den Unterklassentyp geändert wird.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.