第八章 多态总结 协变返回类型 向下转型 和运行时类型识别继承中 is-a 和 is-like-a及子类父类的方法调用(ClassCastException)

1.协变返回类型

  • 表示子类中被覆盖的方法可以返回父类方法的返回类型的某种子类类型。
    class Grain {
    	public String toString() {
    		return "Grain";
    	}
    }
    
    class Wheat extends Grain {
    	public String toString() {
    		return "Wheat";
    	}
    }
    
    class Mill {
    	Grain process() {
    		return new Grain();
    	}
    }
    
    class WheatMill extends Mill {
    	/**
    	 * 重写父类的process方法,可以看到返回类型改成了Grain的子类了,它是一个新方法吗,不是,
    	 * 这就是协变返回类型,覆盖方法可以返回父类返回方法类型的子类 在这里
    	 * WheatMill是Mill的子类,process()为WheatMill重写Mill的方法,
    	 * Mill中的返回类型是Grain,WheatMill的返回类型是Wheat,Wheat是Grain的子类
    	 * 
    	 * Java SE5 之前的版本将强制process的覆盖方法返回Grain,而不能返回其子类型Wheat,
    	 * 协变类型可以
    	 */
    	Wheat process() {
    		return new Wheat();
    	}
    }
    
    public class CovariantReturn {
    	public static void main(String[] args) {
    		Mill m = new Mill();
    		// 这儿的g是Grain类型的引用,而mill的process方法返回的也是Grain对象
    		Grain g = m.process();
    		System.out.println(g);
    		m = new WheatMill();
    		g = m.process();
    		System.out.println(g);
    	}
    }
    

2.is-a和is-like-a

  • is-a 是一个的关系:这是一种纯粹的继承关系,即父类中有多少方法,子类中重写多少方法,不能自己扩展方法。
  • is--like-a 像是一个的关系:可以重写相应的方法,也可以扩展相应的一些方法,比较灵活。
  • is-like-a的关系有一个问题,比如List list = new ArrayList(); 那么list这样一个引用只能调用List中有的,ArrayList中有的或没有的方法,不能调用ArrayList中扩展的方法。

    这种情况下必须知道确切的类型才能访问ArrayList中所扩充的方法。也就引出了下面的向下转型。

3.向下转型与运行时类型识别

  • 与向上转型相反,是往继承图向下移动。
  • 向上转型会丢失方法,而向下转型会获得方法
  • JAVA 是重类型的语言,所有的转型都会得到检查,即使进行一次普通的括弧形式的类型转换,在进入运行期是仍然会对其进行检查,以便确保得到我们希望的那种类型。

    否则就会抛出ClassCastException 异常。
  • /**
     * is-like
     * is-like-a
     * 向下转型
     * @date 2016-8-20 下午12:28:32 
     */
    class Useful{
    	public void f(){}
    	public void g(){}
    }
    class MoreUseful extends Useful{
    	public void f(){}
    	public void g(){}
    	public void u(){}
    	public void v(){}
    	public void w(){}
    }
    public class RTTI {
    	public static void main(String[] args) {
    		Useful[] x = {
    				new Useful(),
    				new MoreUseful()
    		};
    		x[0].f();
    		//向下转型 获取方法
    		((MoreUseful) x[1]).v();
    	}
    }
    
    父类引用访问子类的扩展方法,必须进行向下转型才能获取到。

总结

  • 用继承表达行为间的差异(各个子类是不同的),用字段表示状态上的变化()。
  • 多态可能伴随着继承的存在,但也可能是public 方法 或protect 方法 因为多个类中可能有相同的public方法,这就需要运行时判断是调用哪一个类中的方法了。但大多数是继承。
  • 多态是动态绑定:即在程序运行期间方法调用与方法所在类中的主体相关联并执行其中代码,在运行前无法知道这个方法在哪个类中。
  • 多态是一种不能单独来看待的特性,相反它只能作为类关系“全景”中的一部分,与其他部分协同工作。
  • 少用继承,多用组合,协同作战。






  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值