Co to jest kowariantny typ zwrotu?

105

Co to jest kowariantny typ zwracany w Javie? W ogóle w programowaniu obiektowym?

Wyskakuje
źródło
5
ten post na blogu ( blogs.oracle.com/sundararajan/entry/ ... ) wyjaśnia, dodając tylko do bazy wiedzy tutaj.
Akhil Jain
@AkhilJain: Ten post na blogu jest genialny i prosty. Jest to najlepsze wyjaśnienie, jakie kiedykolwiek widziałem, pokazujące, jak Java obsługuje kowariantne typy zwracane.
kevinarpe
@kevinarpe thanks, cieszę się, że jest to pomocne dla tak wielu osób.
Akhil Jain

Odpowiedzi:

143

Zwrot kowariantny oznacza, że ​​w przypadku przesłaniania metody zwracany typ metody zastępującej może być podtypem typu zwracanego metody zastępowanej.

Aby wyjaśnić to na przykładzie, typowym przypadkiem jest Object.clone()- który jest zadeklarowany w celu zwrócenia typu Object. Możesz to zmienić we własnej klasie w następujący sposób:

public class MyFoo
{

   ...

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

Zaletą jest to, że każda metoda, która zawiera jawne odwołanie do obiektu MyFoo, będzie mogła wywołać clone()i wiedzieć (bez rzutowania), że zwracana wartość jest instancją MyFoo. Bez kowariantnych typów zwracanych, zastąpiona metoda w MyFoo musiałaby zostać zadeklarowana jako zwracająca Object- a więc wywołanie kodu musiałoby jawnie obniżyć wynik wywołania metody (nawet jeśli obie strony "wiedzą", że zawsze może to być tylko instancja MyFoo ).

Zauważ, że nie ma w tym nic specjalnego clone()i że każda nadpisana metoda może mieć kowariantny zwrot - użyłem jej jako przykładu tutaj, ponieważ jest to standardowa metoda, w której jest to często przydatne.

Andrzej Doyle
źródło
czy nie ma to być związane z List<Foo>i List<FooBar>?
zinking
2
To kowariantne typy w szerszym sensie, a nie tylko kowariantny typ zwracany, o który pytamy tutaj. Jest to jednak ta sama podstawowa zasada - możesz pomyśleć o definicji najwyższego poziomu clone()jako bycie a Method<Void, Object>i zapytać, czy bardziej szczegółowe Method<Void, MyFoo>można przypisać do tego typu nadrzędnego. Co tak jest, wtedy i tylko wtedy, gdy metody Java są kowariantne w zwracanym typie.
Andrzej Doyle
38

Oto kolejny prosty przykład:

Animal klasa

public class Animal {

    protected Food seekFood() {

        return new Food();
    }
}

Dog klasa

public class Dog extends Animal {

    @Override
    protected Food seekFood() {

        return new DogFood();
    }
}

Jest możliwe, aby zmienić typ powrotnego ruchu Dogjest seekFood()metodą do DogFood- podklasy Food, jak pokazano poniżej:

@Override
protected DogFood seekFood() {

    return new DogFood();
}

To doskonale nadrzędnym prawnej i rodzaju powrót Dog„s seekFood()metoda jest znana jako kowariantna typ zwracany .

Mohamed ALOUANE
źródło
8

Od wydania JDK 1.5 typy kowariantne zostały wprowadzone w Javie. i wyjaśnię ci to w prostym przypadku: Kiedy nadpisujemy funkcję, funkcja może wprowadzać zmiany w jej zachowaniu , właśnie to czytasz w większości książek, ale to, czego {autorzy} przegapiają polega na tym, że możemy również zmienić typ zwracanej wartości. sprawdź poniższy link dla wyjaśnienia, możemy zmienić typ zwracania, o ile można go przypisać do typu zwracanego wersji podstawowej metody.

Więc ta funkcja zwracania typów pochodnych nazywa się KOWARIANT ...

Czy metody przesłonięte mogą różnić się typem zwracania?

Prezydent Pratik
źródło
7

kowariantne Zwracane typy oznaczają po prostu zwrócenie własnego odwołania do klasy lub odwołania do klasy potomnej.

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
źródło
1
Obejmuje również przypadek, w którym Parent.foo()zwraca niepowiązany typ Ai Child.foo()zwraca typ Bpochodzący z A.
Davis Herring
2

Aby dodać do powyższych odpowiedzi, przesłonięcie jest możliwe wśród wspólnych typów zwracanych, z zastrzeżeniem, że typ zwracany metody przesłaniającej (metoda podklasy) powinien być podklasą typu zwracanego metody przesłoniętej (metoda nadrzędnej). Jest to ważne od wersji Java 5.

Życie Pai
źródło
1

Kowariantny typ zwrotu określa, że ​​typ zwracany może różnić się w tym samym kierunku co podklasa

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

Przed wersją Java 5 nie można było przesłonić żadnej metody poprzez zmianę zwracanego typu. Ale teraz, odkąd Java5,

możliwe jest przesłonięcie metody poprzez zmianę zwracanego typu, jeśli podklasa przesłania jakąkolwiek metodę, której typem zwracanym jest Non-Primitive, ale zmienia typ zwracany na typ podklasy.

Keshav Gera
źródło
1
  • Pomaga to uniknąć mylących rzutów typów obecnych w hierarchii klas, a tym samym sprawia, że ​​kod jest czytelny, użyteczny i konserwowalny.
  • Podczas nadpisywania
    metod możemy mieć bardziej szczegółowe typy zwracane .

  • Pomoc w zapobieganiu wyjątkom ClassCastExceptions w czasie wykonywania zwrotów

źródło: www.geeksforgeeks.org

Arun Raaj
źródło
0
  • Kowariantny typ zwracany w Javie pozwala zawęzić zwracany typ metody przesłoniętej.
  • Ta funkcja pomoże uniknąć rzucania w dół po stronie klienta. Pozwala programiście na programowanie bez konieczności sprawdzania typu i rzutowania w dół.
  • Kowariantny typ zwracany zawsze działa tylko w przypadku innych niż pierwotne typy zwracane.
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();
    }
}

Inny przykład pochodzi z Javy,

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
źródło
0

Przed wersją Java 5 nie można było przesłonić żadnej metody przez zmianę zwracanego typu. Ale teraz, od wersji Java5, możliwe jest przesłonięcie metody poprzez zmianę zwracanego typu, jeśli podklasa przesłania jakąkolwiek metodę, której typem zwracanym jest Non-Primitive, ale zmienia typ zwracany na typ podklasy.


źródło