116

Java中的协变返回类型是什么?在一般的面向对象编程中?

4

9 回答 9

152

协变返回,意味着当一个方法重写时,重写方法的返回类型允许是被重写方法的返回类型的子类型。

为了用一个例子来说明这一点,一个常见的情况是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(),任何被覆盖的方法都可以有一个协变返回——我在这里用它作为一个例子,因为它是一个标准方法,这通常很有用。

于 2009-12-10T17:24:12.803 回答
45

这是另一个简单的例子:

Animal班级

public class Animal {

    protected Food seekFood() {

        return new Food();
    }
}

Dog班级

public class Dog extends Animal {

    @Override
    protected Food seekFood() {

        return new DogFood();
    }
}

Dog可以将'seekFood()方法的返回类型修改为DogFood- 的子类Food,如下所示:

@Override
protected DogFood seekFood() {

    return new DogFood();
}

这完全是一个合法的覆盖,并且Dog'seekFood()方法的返回类型被称为协变返回类型

于 2015-09-14T19:36:34.497 回答
10

从 JDK 1.5 版本开始,Java 中引入了协变类型。我会用一个简单的例子向你解释:当我们重写一个函数时,这个函数被允许改变它的行为,这是你在大多数书中读到的,但他们{作者}错过了什么是我们也可以更改返回类型。检查下面的链接以澄清我们可以更改返回类型,只要它可以分配给方法的基本版本的返回类型。

所以这个返回派生类型的特性叫做 COVARIANT...

被覆盖的方法可以在返回类型上有所不同吗?

于 2014-03-19T07:46:32.607 回答
9

协变返回类型仅仅意味着返回自己的类引用或其子类引用。

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

}
于 2016-09-18T13:49:14.527 回答
2

为了补充上述答案,在协变返回类型之间可以进行覆盖,但约束是覆盖方法(子类方法)的返回类型应该是被覆盖方法(超类方法)的返回类型的子类。这从 Java 5 开始有效。

于 2019-10-26T17:53:05.083 回答
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 开始,

如果子类覆盖了返回类型为非原始的任何方法,但将其返回类型更改为子类类型,则可以通过更改返回类型来覆盖方法。

于 2017-06-12T11:23:57.980 回答
1
  • 它有助于避免混淆类层次结构中存在的类型转换,从而使代码可读、可用和可维护。

  • 在覆盖方法时,我们可以自由地拥有更具体的返回类型。

  • 帮助防止返回时出现运行时 ClassCastExceptions

参考:www.geeksforgeeks.org

于 2018-04-18T22:29:38.420 回答
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,

一元运算符.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;
    }
}
于 2017-06-10T08:05:46.317 回答
0

在 Java5 之前,无法通过更改返回类型来覆盖任何方法。但是现在,从 Java5 开始,如果子类覆盖了返回类型为非原始类型的任何方法,但将其返回类型更改为子类类型,则可以通过更改返回类型来覆盖方法。

于 2019-03-13T17:45:36.957 回答