Qu'est-ce qu'un type de retour covariant?

105

Qu'est-ce qu'un type de retour covariant en Java? Dans la programmation orientée objet en général?

Pops
la source
5
ce billet de blog ( blogs.oracle.com/sundararajan/entry/… ) explique, en ajoutant simplement à la base de connaissances ici.
Akhil Jain
@AkhilJain: Ce billet de blog est brillant et simple. C'est la meilleure explication par exemple que j'ai jamais vue sur la façon dont Java prend en charge les types de retour covariants.
kevinarpe
@kevinarpe merci, je suis heureux que cela soit utile à tant de gens.
Akhil Jain

Réponses:

143

Retour covariant, signifie que lorsque l'on remplace une méthode, le type de retour de la méthode de substitution est autorisé à être un sous-type du type de retour de la méthode remplacée.

Pour clarifier cela avec un exemple, un cas courant est Object.clone()- qui est déclaré pour renvoyer un type de Object. Vous pouvez remplacer cela dans votre propre classe comme suit:

public class MyFoo
{

   ...

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

L'avantage ici est que toute méthode contenant une référence explicite à un objet MyFoo pourra invoquer clone()et savoir (sans conversion) que la valeur de retour est une instance de MyFoo. Sans les types de retour covariants, la méthode surchargée dans MyFoo devrait être déclarée pour return Object- et donc l'appel du code devrait explicitement réduire le résultat de l'appel de méthode (même si les deux côtés "savent", il ne peut être qu'une instance de MyFoo ).

Notez qu'il n'y a rien de spécial clone()et que toute méthode surchargée peut avoir un retour covariant - je l'ai utilisé comme exemple ici car c'est une méthode standard où cela est souvent utile.

Andrzej Doyle
la source
n'est-il pas censé être lié à List<Foo>et List<FooBar>?
zinking le
2
Il s'agit de types covariants dans un sens plus large plutôt que simplement du type de retour covariant interrogé ici. C'est le même principe sous-jacent, cependant - vous pouvez penser à la définition de niveau supérieur de clone()comme étant un Method<Void, Object>, et demander si le plus spécifique Method<Void, MyFoo>est attribuable à ce type de parent. Ce qui est le cas, si et seulement si les méthodes Java sont covariantes dans leur type de retour.
Andrzej Doyle le
38

Voici un autre exemple simple:

Animal classe

public class Animal {

    protected Food seekFood() {

        return new Food();
    }
}

Dog classe

public class Dog extends Animal {

    @Override
    protected Food seekFood() {

        return new DogFood();
    }
}

Il est possible de modifier le type de retour de la méthode Dogs seekFood()en DogFood- une sous-classe de Food, comme indiqué ci-dessous:

@Override
protected DogFood seekFood() {

    return new DogFood();
}

C'est parfaitement une substitution légale, et le type de retour de Dogla seekFood()méthode de est connu sous le nom de type de retour covariant .

Mohamed ALOUANE
la source
8

Depuis la sortie de JDK 1.5, des types covariants ont été introduits dans Java. et je vais vous l'expliquer avec un cas simple: lorsque nous surchargons une fonction, la fonction est autorisée à modifier son comportement, c'est ce que vous lisez dans la plupart des livres, mais ce qu'ils {auteurs} manquent est que nous pouvons également changer le type de retour. Vérifiez le lien ci-dessous pour plus de précisions, nous pouvons changer le type de retour tant qu'il peut être attribué au type de retour de la version de base de la méthode.

Donc, cette fonctionnalité de retour de types dérivés est appelée COVARIANT ...

Les méthodes remplacées peuvent-elles différer dans le type de retour?

PrésidentPratik
la source
7

covariant Les types de retour signifie simplement renvoyer sa propre référence de classe ou sa référence de classe enfant.

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

}
Dhiraj
la source
1
Il inclut également le cas où Parent.foo()renvoie un type non liéA et Child.foo()retourne un type Bdérivé de A.
Davis Herring
2

Pour ajouter aux réponses ci-dessus, le remplacement est possible parmi les types de retour co-variant, avec la contrainte que le type de retour de la méthode de substitution (méthode de sous-classe) doit être une sous-classe du type de retour de la méthode de substitution (méthode de superclasse). Ceci est valable à partir de Java 5.

Vie de Pai
la source
1

Le type de retour covariant spécifie que le type de retour peut varier dans le même sens que la sous-classe

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

Avant Java 5, il n'était pas possible de remplacer une méthode en modifiant le type de retour. Mais maintenant, depuis Java5,

il est possible de remplacer la méthode en changeant le type de retour si la sous-classe remplace toute méthode dont le type de retour est Non-primitif mais elle change son type de retour en type de sous-classe.

Keshav Gera
la source
1
  • Cela permet d'éviter de confondre les castes de types présentes dans la hiérarchie des classes et de rendre ainsi le code lisible, utilisable et maintenable.
  • Nous avons la liberté d'avoir des types de retour plus spécifiques lors de la substitution de
    méthodes.

  • Aide à empêcher les ClassCastExceptions d'exécution sur les retours

référence: www.geeksforgeeks.org

Arun Raaj
la source
0
  • Le type de retour covariant en java permet de réduire le type de retour de la méthode remplacée.
  • Cette fonctionnalité aidera à éviter la diffusion descendante côté client. Il permet au programmeur de programmer sans avoir besoin de vérification de type et de conversion descendante.
  • Le type de retour covariant fonctionne toujours uniquement pour les types de retour non primitifs.
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();
    }
}

Un autre exemple vient de 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;
    }
}
snr
la source
0

Avant Java5, il n'était pas possible de remplacer une méthode en modifiant le type de retour. Mais maintenant, depuis Java5, il est possible de remplacer la méthode en changeant le type de retour si la sous-classe remplace toute méthode dont le type de retour est Non-primitif mais elle change son type de retour en type de sous-classe.


la source