Що таке коваріантний тип повернення?


105

Що таке коваріантний тип повернення на Java? В об'єктно-орієнтованому програмуванні взагалі?


5
ця публікація в блозі ( blogs.oracle.com/sundararajan/entry/… ) пояснює, лише додавши тут базу знань.
Ахіл Джайн

@AkhilJain: Ця публікація в блозі геніальна і проста. Це найкраще пояснення, яке я коли-небудь бачив, як Java підтримує коваріантні типи повернення.
кевінарпе

@kevinarpe дякую, я радий, що це корисно багатьом людям.
Ахіл Джайн

Відповіді:


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>і List<FooBar>?
цинкування

2
Це типи коваріантів у більш широкому сенсі, а не просто тип коваріантного повернення, про який тут просили. Це є тим самим основним принципом - ви можете подумати про визначення верхнього рівня clone()як "a" Method<Void, Object>і запитати, чи Method<Void, MyFoo>призначається більш конкретне для цього типу батьків. Що це, якщо і лише тоді, коли методи Java коваріантні у своєму поверненому типі.
Анджей Дойл

38

Ось ще один простий приклад:

Animal клас

public class Animal {

    protected Food seekFood() {

        return new Food();
    }
}

Dog клас

public class Dog extends Animal {

    @Override
    protected Food seekFood() {

        return new DogFood();
    }
}

Можна змінити тип повернення методу Dog's seekFood()до DogFoodпідкласу Food, як показано нижче:

@Override
protected DogFood seekFood() {

    return new DogFood();
}

Це абсолютно юридичне переосмислення, а тип повернення методу Dog' seekFood()відомий як коваріантний тип повернення .


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()повертає непов'язаний тип Aі Child.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;
    }
}

Функція.java

@FunctionalInterface
public interface Function<T, R> {

    ........
    ........
    ........
    ........

    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

0

Перед Java5 не вдалося змінити жоден метод, змінивши тип повернення. Але тепер, оскільки Java5, метод можна замінити, змінивши тип повернення, якщо підклас замінює будь-який метод, тип повернення якого є Непримітивним, але він змінює свій тип повернення на тип підкласу.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.