专栏首页WindCoderJava漫谈-协变返回类型

Java漫谈-协变返回类型

Java SE5中添加协变返回类型,表示在导出类中的被覆盖方法可以返回基类方法的返回类型的某种导出类型

如现有:导出类WheatMill,被覆盖方法process(),基类Mill,基类方法的返回类型Grain,其导出类型Wheat。

类文件

Mill.java:基类

基类Mill

/**
 * 磨坊; 工厂; 磨粉机; 榨汁机;
 */
public class Mill {
    Grain process(){
        return new Grain();
    }
}

Grain.java:基类方法的返回类型

基类方法的返回类型Grain

/**
 * 谷物(Grain ),可以在工厂(Mill)中被加工(process)
 */
public class Grain {
    private String name;

    @Override
    public String toString() {
        return "Grain{}---谷物";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

WheatMill.java:Mill的导出类(即其子类)

基类Mill的导出类WheatMill

/**
 * 工厂/磨坊(Mill)的导出类小麦磨坊(Mill)
 *
 */
public class WheatMill extends Mill {
    /**
     * 重写Mill的process()方法
     * 协变返回类型允许返回更具体的Wheat类型,亦即此时的Wheat为协变返回类型
     * @return
     */
    Wheat process(){
        return new Wheat();
    }
}

Wheat.java:谷物(Grain)的导出类小麦(Wheat)

基类Mill的导出类WheatMill

/**
 * 谷物(Grain)的导出类小麦(Wheat)
 */
public class Wheat extends Grain{
    private String color;

    @Override
    public String toString() {
        return "Wheat{}---小麦: " + getName() + " , the color :"+ this.color;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }
}

CovariantReturnDemo.java:运行demo

测试类CovariantReturnDemo

/**
*By windcoder.com
*/
public class CovariantReturnDemo {
    public static void main(String[] args) {
        // 创建基类Mill的实例m
        Mill m = new Mill();
        // 获取m的返回类型Grain的实例g
        Grain g = m.process();
        //设置g的名称并打印
        g.setName("windCoder.com");
        System.out.println(g);
        System.out.println(g.getName());
        //将m重新分配给其类型(基类Mill)的导出类(WheatMill),由于m自身是Mill,此时自动向上转型
        m = new WheatMill();
        //获取m的返回类型Grain的实例g
        g =m.process();
        g.setName("bulu");
        //! g.setColor("red");   //---此时g的类型依旧是基类Grain,故不存在其子类(Wheat)中的setColor()方法
        System.out.println(g);
        System.out.println(g.getName());
        // 因为是协变返回类型,所以可以向下转型
        Wheat w = (Wheat) g;
        w.setColor("red");
        System.out.println(g);
    }
}

运行结果

Grain{}---谷物: heihei
heihei
Wheat{}---小麦: bulu , the color :null
bulu
Wheat{}---小麦: bulu , the color :red

解析

与较早版本差别:

较早版本将强制process()的覆盖版必须返回Grain,而不能返回Wheat。

但Wheat是从Grain导出的,因而也应该是一种合法的返回类型。

协变返回类型允许返回更具体的Wheat类型

扩:

里氏代换原则(任何基类可以出现的地方,子类一定可以出现)

重写/覆盖规则:

  •  1.重写方法不能比被重写方法限制有更严格的访问级别。
  • 2.参数列表必须与被重写方法的相同。
  • 3.返回类型必须与被重写方法的返回类型相同。
  • 4.重写方法不能抛出新的异常或者比被重写方法声明的检查异常更广的检查异常。但是可以抛出更少,更有限或者不抛出异常。
  • 5.不能重写被标识为final的方法。
  • 6.如果一个方法不能被继承,则不能重写它。如private方法

可见此处demo中WheatMill对Mill的process()方法的重写违反了重写规则3,但Wheat属于Grain的子类(即Wheat IS-A Grain),所以在向上的继承树转换时会隐式完成。此处的Wheat即成了协变返回类型。

相关下载

点击下载

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • WordPress代码实现自动拒绝包含特定关键词的垃圾评论

    经常受到类似的垃圾评论,有点懒得动手删了,于是百度出自动拒绝特定关键字的评论的方法并记于此处。

    汐楓
  • 当nz-checkbox-group多选框组遇上必选校验

    今天表单中用到ng-zorro-antd组件的多选框nz-checkbox-group,最开始用的是响应式表单的验证+响应式表单的验证,结果总是无法达到预期效果...

    汐楓
  • 如何修复Ubuntu 14.04 系统设置丢失的问题

    其实遇到这个问题的一个最主要的原因是之前执行过卸载ibus输入法的操作,所以为了避免这个问题请不要卸载ibus输入法,大家依然可以安装fcitx输入法使用。

    汐楓
  • Head First设计模式——蝇量模式和解释器模式

    在一个设计房子的平台中,周围要加上一些树,树有一个坐标XY坐标位置,而且可以根据树的年龄动态将自己绘制出来。如果我们创建许多树之后,会有许多树的实例对象。使用一...

    SpringSun
  • (52) 抽象容器类 / 计算机程序的思维逻辑

    查看历史文章,请点击上方链接关注公众号。 从38节到51节,我们介绍的都是具体的容器类,上节我们提到,所有具体容器类其实都不是从头构建的,它们都继承了一些抽象容...

    swiftma
  • 23种设计模式详解(六)

    南风
  • Java方法的嵌套与递归调用

    方法嵌套的概念其实比较好理解,就是在调用方法的过程中又遇到了方法的调用,在刚开始接触的时候虽然在逻辑上能够理解为什么运行结果是这样的,但是对于代码执行的过程还是...

    聚沙成塔
  • 装饰模式

    概述 23种设计模式之一,英文叫DecoratorPattern,中文也叫装饰模式、修饰模式。装饰模式是在不改变类文件和不使用继承的情况下,运行期动态扩展一个对...

    高爽
  • 代理模式

    mySoul
  • 设计模式之抽象工厂模式

    tanoak

扫码关注云+社区

领取腾讯云代金券