前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java漫谈-协变返回类型

Java漫谈-协变返回类型

作者头像
WindCoder
发布2018-09-19 15:55:48
1K0
发布2018-09-19 15:55:48
举报
文章被收录于专栏:WindCoderWindCoder

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

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

类文件

Mill.java:基类

基类Mill

代码语言:javascript
复制
/**
 * 磨坊; 工厂; 磨粉机; 榨汁机;
 */
public class Mill {
    Grain process(){
        return new Grain();
    }
}

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

基类方法的返回类型Grain

代码语言:javascript
复制
/**
 * 谷物(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

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

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

基类Mill的导出类WheatMill

代码语言:javascript
复制
/**
 * 谷物(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

代码语言:javascript
复制
/**
*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);
    }
}

运行结果

代码语言:javascript
复制
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即成了协变返回类型。

相关下载

点击下载

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 类文件
    • Mill.java:基类
      • Grain.java:基类方法的返回类型
        • WheatMill.java:Mill的导出类(即其子类)
          • Wheat.java:谷物(Grain)的导出类小麦(Wheat)
            • CovariantReturnDemo.java:运行demo
              • 运行结果
              • 解析
                • 与较早版本差别:
                  • 扩:
                    • 重写/覆盖规则:
                    • 相关下载
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档