Cos'è un tipo restituito covariante?


105

Che cos'è un tipo restituito covariante in Java? Nella programmazione orientata agli oggetti in generale?


5
questo post del blog ( blogs.oracle.com/sundararajan/entry/… ) spiega, aggiungendo solo fino alla knowledge base qui.
Akhil Jain

@AkhilJain: Quel post sul blog è brillante e semplice. È la migliore spiegazione per esempio che abbia mai visto per come Java supporta i tipi restituiti covarianti.
kevinarpe

@kevinarpe grazie, sono contento che sia utile a così tante persone.
Akhil Jain

Risposte:


143

Restituzione covariante, significa che quando si sovrascrive un metodo, il tipo restituito del metodo sovrascritto può essere un sottotipo del tipo restituito del metodo sostituito.

Per chiarire questo con un esempio, un caso comune è Object.clone()- che viene dichiarato restituire un tipo di Object. Puoi sovrascriverlo nella tua classe come segue:

public class MyFoo
{

   ...

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

Il vantaggio qui è che qualsiasi metodo che contiene un riferimento esplicito a un oggetto MyFoo sarà in grado di invocare clone()e sapere (senza casting) che il valore restituito è un'istanza di MyFoo. Senza i tipi restituiti covarianti, il metodo sovrascritto in MyFoo dovrebbe essere dichiarato per restituire Object- e quindi chiamare il codice dovrebbe esplicitamente abbassare il risultato della chiamata al metodo (anche se entrambe le parti "sanno" che può essere sempre e solo un'istanza di MyFoo ).

Nota che non c'è niente di speciale clone()e che qualsiasi metodo sovrascritto può avere un ritorno covariante: l'ho usato come esempio qui perché è un metodo standard in cui questo è spesso utile.


non dovrebbe essere correlato con List<Foo>e List<FooBar>?
Zinking

2
Si tratta di tipi covarianti in un senso più ampio piuttosto che solo del tipo restituito covariante chiesto qui. È lo stesso principio di base, tuttavia: puoi pensare alla definizione di primo livello di clone()essere a Method<Void, Object>e chiederti se il più specifico Method<Void, MyFoo>è assegnabile a quel tipo genitore. Che è, se e solo se i metodi Java sono covarianti nel loro tipo di ritorno.
Andrzej Doyle

38

Ecco un altro semplice esempio:

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

È possibile modificare il tipo di ritorno del Dog's seekFood()metodo DogFood- una sottoclasse di Food, come mostrato di seguito:

@Override
protected DogFood seekFood() {

    return new DogFood();
}

Questo è perfettamente un imperativo legale, e il tipo di ritorno di Dog's seekFood()metodo è noto come tipo restituito covariante .


8

Dal rilascio di JDK 1.5, i tipi covarianti sono stati introdotti in Java. e te lo spiegherò con un semplice caso: quando sovrascriviamo una funzione, la funzione può apportare modifiche al suo comportamento questo è ciò che puoi leggere nella maggior parte dei libri, ma ciò che gli {autori} perdono è che possiamo cambiare anche il tipo di ritorno. controlla sotto il link per chiarimenti possiamo cambiare il tipo di ritorno purché possa essere assegnato al tipo di ritorno della versione Base del metodo.

Quindi questa caratteristica di restituire i tipi derivati ​​è chiamata COVARIANT ...

I metodi sostituiti possono differire nel tipo restituito?


7

Tipi restituiti covarianti significa semplicemente restituire il proprio riferimento alla classe o il suo riferimento alla classe figlia.

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
Include anche il caso in cui Parent.foo()restituisce un tipo non correlatoA e Child.foo()restituisce un tipo Bderivato da A.
Davis Herring

2

Per aggiungere alle risposte precedenti, è possibile eseguire l'override tra i tipi restituiti co-variant, con il vincolo che il tipo restituito del metodo sovrascritto (metodo della sottoclasse) dovrebbe essere una sottoclasse del tipo restituito del metodo sostituito (metodo della superclasse). Questo è valido da Java 5 in poi.


1

Il tipo restituito covariante specifica che il tipo restituito può variare nella stessa direzione della sottoclasse

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

Prima di Java 5, non era possibile sovrascrivere alcun metodo modificando il tipo restituito. Ma ora, da Java5,

è possibile sovrascrivere il metodo cambiando il tipo restituito se la sottoclasse sovrascrive qualsiasi metodo il cui tipo restituito è Non primitivo ma cambia il tipo restituito in tipo sottoclasse.


1
  • Aiuta a evitare di confondere i tipi di cast presenti nella gerarchia di classi e quindi a rendere il codice leggibile, utilizzabile e gestibile.
  • Abbiamo la libertà di avere tipi di restituzione più specifici quando sovrascriviamo i
    metodi.

  • Aiuta a prevenire ClassCastExceptions in fase di esecuzione sui resi

riferimento: www.geeksforgeeks.org


0
  • Il tipo restituito covariante in java, consente di restringere il tipo restituito del metodo sostituito.
  • Questa funzione aiuterà a evitare il down casting dal lato client. Consente al programmatore di programmare senza la necessità di controllo del tipo e down casting.
  • Il tipo restituito covariante funziona sempre solo per i tipi restituiti non primitivi.
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 altro esempio è da 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

Prima di Java5, non era possibile sovrascrivere alcun metodo modificando il tipo restituito. Ma ora, a partire da Java5, è possibile sovrascrivere il metodo cambiando il tipo restituito se la sottoclasse sovrascrive qualsiasi metodo il cui tipo restituito è Non primitivo ma cambia il tipo restituito in tipo sottoclasse.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.