目标:
1. 知道接口也默认继承Object类
2. 感受继承和重写在向上转型中的作用有多大
引出问题:
在我用 List接口的引用list 接收ArrayList这个集合类的实例时(此处发生向上转型),偶然发现,咦,引用list怎么能调用Object类中的方法?我知道所有类都会默认继承Object类,难道说接口也会继承Object类吗?
那么,接口类型的引用c可以调用哪些方法呢?
例子对比:
带着这些问题,我们先来看2个例子,对比一下:
(1)类B继承类A,类B中重写Object类中的toString方法,A a = new B();
(2)类B实现接口A,类B中重写Object类中的toString方法,A a = new B();
我们比较熟悉子类和父类之间发生的向上转型。来看,
1)类B继承类A,类B中重写Object类中的toString方法,A a = new B();
类A会继承Object类中的所有方法,类A中除了有自己的方法,还有Object类中的方法。
A a = new B();发生了向上转型
a可以调用的方法有:
1. 父类A中特有的方法(包括类A自己特有的方法和Object类中特有的方法)特有即没有被重写
2. 子类B中重写的方法(子类重写的方法可能有:父类A中的方法以及Object类中的方法)
只要这个方法被重写了,就只会调用重写后的方法。如下:子类B中重写了toString方法。
2)类B实现接口A,类B中重写Object类中的toString方法,A a = new B();
接口A继承Object类。接口A中除了有自己的方法,还有继承的Object类中的方法。
A a = new B();发生了向上转型
a可以调用的方法有:
1. 父接口A中特有的方法(包括父接口A自己特有的方法和Object类中特有的方法)特有即没有被重写
2. 子类B中重写的方法(子类重写的方法可能有:父接口A中的抽象方法以及Object类中的方法)
只要这个方法被重写了,就只会调用重写后的方法。如下:子类B中重写了toString方法。
综上:发生向上转型,父类/父接口的引用可以调用的方法是:
1. 父类/父接口特有的方法
2. 子类中重写的方法
得出结论:
没错,接口也默认继承Object类。
那我们在回过头来看文章开头的问题:
为什么list可以调用toString方法?因为父接口继承Object类,所以父接口List中除了有自己的方法还有Object类中的方法,List类型的list当然可以调用自己的方法喽。
接着,我们发现,不对啊,list调用父接口(继承的Object类)的toString方法不是应该输出的“地址”吗,怎么不是?
你可别忘了,方法被子类重写后,就会调用子类重写的方法了。所以我们去看看子类ArrayList中的方法。
有同学又有疑问了,你骗人,ArrayList类中根本没有toString方法,别着急,我们来看它的父类,如下图:
最后,我们在AbsrtactCollection类中发现了toString方法。
子类会继承父类所有的成员变量和成员方法。一路继承下来,ArrayList这个集合类中就会有toString方法啦。
对于接口List而言,ArrayList算子类,子类中重写了父接口中的方法,调用这个方法时,会调用重写的那个。于是list调用toString方法,会调用重写的那个,不会输出地址。
思考:
从这里,我们是不是就能体会到继承的牛逼之处了,就像继承财产,只要继承了,就是我的了。(比如上面,List接口继承Object类,Object类中的方法都是我List类的啦。)
还有重写的必要性,在一个类中重写了某个方法,这个重写的方法可以被一路继承,被好多类都拥有。(比如上面,AbsrtactCollection类中重写的toString方法被一路继承,ArrayList等类都拥有了)
还有向上转型,父类的引用可以调用子类重写的方法,那被一路继承的重写的方法,也可以被调用到啦。(比如上面,父类的引用list可以调用子类重写的toString方法)
不要看简简单单的一行代码:String s = list.toString(); 输出的不是“地址”这个问题,
要想明白这个问题,可是要知道很多知识点的。要知道继承,重写,向上转型,以及类和接口都会继承Object类等等。
最后:
关于接口继承Object类,还有很多知识未了解。像接口继承Object类,一个类可以继承多个接口,难道会继承多次Object类吗?应该是只会继承一次的。这还待补充。还有关于底层的一些深入了解。这篇先写到这。