2009-12-10 102 views
75

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

+4

此博客文章(https://blogs.oracle.com/sundararajan/entry/covariant_return_types_in_java)解释说,只是在这里添加知识库。 – 2013-11-10 10:29:04

+0

@AkhilJain:那篇博文很出色,很简单。这是我见过的关于Java如何支持协变返回类型的最佳解释。 – kevinarpe 2016-10-11 09:58:00

+0

@kevinarpe谢谢,我很高兴这对许多人有帮助。 – 2016-10-12 05:28:32

回答

107

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

为了说明这一点,一个常见的情况是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()没有什么特别之处,任何重写的方法都可以有一个协变返回 - 我在这里用它作为示例,因为它是一个常用的标准方法。

+0

是不是应该和'List '和'List '有关? – zinking 2016-06-12 08:53:24

+2

这是广义上的协变类型,而不仅仅是在这里被问到的协变**返回**类型。然而,它的基本原理是相同的 - 你可以将clone()的顶层定义看作是一个“Method ”,并询问更具体的方法是否可以分配给父类型。它是什么,当且仅当Java方法在返回类型中是协变的。 – 2016-06-14 11:58:32

5

从JDK 1.5发布以来,协变类型在Java中引入。我会用一个简单的例子向你解释:当我们重写一个函数时,该函数允许修改它的行为这就是你在大多数书籍中阅读的内容,但是他们(作者)错过了什么我们可以改变返回类型。 检查下面的链接澄清我们可以改变返回类型,只要它可以分配给方法的基本版本的返回类型。

于是久违派生类型的这种功能称为协变...

Can overridden methods differ in return type?

27

这里有另外一个简单的例子:

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返回类型“方法被称为协变返回类型

3

协变返回类型仅仅意味着返回自己的类引用或其子类的引用。 类父 { //它包含数据构件和数据的方法 }

class Child extends Parent 
{ 
//it contain data member and data method 
//covariant return 
public Parent methodName() 
    { 
    return new Parent(); 
      or 
     return Child(); 
    } 

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

Function.java

@FunctionalInterface 
public interface Function<T, R> { 

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

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

协变返回类型指明,返回类型也可以在相同的方向上的子类

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的,

可以通过,如果子类覆盖任何方法 其返回类型为非原始 但它改变了它的返回类型的子类类型改变的返回类型 重写方法。