20172308《程序设计与数据结构》第八周学习总结
20172308 2017-2018-2 《Java程序设计》第八周学习总结
教材学习内容总结
1.多态
a.体现:
父类引用指向了自己的子类对象;
父类的引用接受自己的子类对象。(eg:父类 f = new 子类() ;
)
b.好处:大大提高了程序的扩展性。
c.前提:类与类之间有关系(继承,实现)
d.弊端:提高了扩展性,但只能使用父类的引用访问父类的成员(对于子类有的而父类没有的方法,不能直接调用)
解决办法:实际上这种声明父类 f = new 子类() ;
是一个类型提升的过程(向上转型)。可以通过子类 z =(子类)f ;
强制将父类引用转换成子类类型,然后调用子类的特有方法(这就是一个向下转型过程)。然而能转换的是父类引用指向了自己的子类对象是,该引用可以被提升,也可以被强制转换;而如果是父类类型对象是无法被转成子类对象的(如,父类 f = new 父类() ; 子类 z =(子类)f ;
)
e.特点:在多态中,自始至终都是子类对象在做着变化。
f.类型:由继承实现多态性;利用接口实现多态性
2.排序
a.选择法排序:从第一个元素开始向后扫描整个数列,将最小值与第一个元素交换位置,再从第二个元素开始向后扫描,将最小值与第二个元素交换位置,直到最后。
b.插入法排序:从第二个元素开始与第一个元素比较,第二个小则与其交换位置,否则则不交换;再从第三个元素开始,从第一个元素开始比较,直到比某个元素小则插到这个元素的前面,直到最后一个元素。
比较:两种方法实际排序效率相同,算法执行比较操作次数相同,但选择法排序执行交换次数更少,因此选择法优于插入法。
3.搜索
a.线性搜索:从一个端点开始,以线性方式扫描(与所有元素比较)整个搜索池
b.二分搜索:前提是数组元素是有序的(升序或降序),注意:排除的待搜索数据包括中点元素;若待搜索元素为偶数个,则产生两个中点值,选第一个为新的中点。
比较:算法的选择取决于具体条件(比如,待搜索数组元素为有序排列,则二分搜索更有效率;若元素以数组形式存储,线性搜索相对简单)
教材学习中的问题和解决过程
-
问题1:如何理解多态性的弊端,即不能直接调用子类的特有方法:
-
问题1解决过程:参考蓝墨云视频;例如,
父类 f = new 子类() ;
,f.子类方法()
。这个时候这两句话能否通过,要分为两个过程:一是能否通过编译,而是能否运行。在编译的时候,会参阅引用型变量所属的类(即父类),是否有即将调用的方法(即 .子类方法() )。有则通过编译,无则无法通过编译;编译通过,然后是运行阶段,参阅对象所属类中(即子类)是否有调用方法。这里还有一个需要注意的地方,就是上述所说都是针对多态中非静态成员函数的,他们具有可覆盖的功能,因而才体现了多态性;而如果是静态成员(函数和变量),不管是编译还是运行,都参阅的是引用型所属的类(即父类),是否有即将调用的方法。 -
问题2:课本的例10.6,前面有一句话说“Executive(子类)构造方法将自己的信息传递给Employee构造方法”,即:
这句话的意思不是很懂,按照我的理解应该是“子类重写了父类的构造方法啊”。 -
问题2解决过程:百度。这是C++里的情况,不知道适不适用:原本父类构造的时候就需要参数,子类继承的是父类,没有参数父类的构造函数无法执行。传过去的参数用于父类的构造函数执行(通俗的说,一般用于初始化父类的成员变量等)。参数是传给父类的构造函数的。一般程序的运行顺序是先从父类再到子类,如果想在子类定义时传递参数给父类就要显示地调用父类的构造函数 。这里还明白了前面的一个问题,就是为什么没有在子类构造方法里写super(),编译器会自动调用super()方法,即调用了父类的构造方法:之所以需要调用父类的构造方法是因为在父类中,可能存在私有属性需要在其构造方法内初始化。
【参考资料】:
百度知道
chrisfxs的专栏
风一样的码农的博客
-
问题3:书上说:“如果对象可以自然地由继承的关系关联起来,则通过继承实现多态性;如果对象共同存在的主要问题需要以各自不同的方式进行处理,则通过接口建立多态性”。这句话倒是能理解,但是我感觉各自应该有其的优势吧
-
问题3解决过程:百度了一下:“接口有利于代码的扩展,而继承则有利于代码功能的修改”,恍然大悟。
【参考资料】:
牧羊人的世界
代码调试中的问题和解决过程
-
问题1:课后习题PP10.1。一开始做这个题目,感觉无从下手,因为这个例题涉及了很多个类,类之间还有继承关系,所以说要用接口来实现,不是很明白从哪里下手
-
问题1解决过程:参考了课本上例题前面的UML类图,蓝墨云的视频资源。首先是第一个问题,这个接口为什么叫Payable。猜测了一下,之所以叫这个,应该是只要实现支付的方法(顺便把toString也写了)。然后就是写这个接口,写下上面所说的其它类当中的方法。接口代码如图:
代码里我写了支付方法有两个,那是因为原先的类里面的支付方法分别叫了这两个名字,这就导致了一个问题:引用接口的类里面不能同时实现这两个方法,所以要把引用接口的类变成抽象类。虽然只要加上abstract就行了,但是后续的还会影响主程序的声明,如图:
用接口类Payable声明了对象personnel并指向了staff2,但由于volunteer类里有一个pay()方法必须得实现,所以在这里还需要像上图中一样,重写这个方法。其他类也是这样,如图:
这里还有一个问题就是如果是抽象的,就无法将其实例化,如图:
这就需要在实例化的时候,重写每个payday方法,如图:
所以,可以从一开始就将所有的支付方法都叫做pay,然后重写就没问题了,引用的类也就不用是抽象的了。 -
问题2:课后习题PP10.5 。Movies的原来的代码如图:
这个程序是通过编写另一个类里的addDVD方法来达到加入DVD信息的目的的,然后将信息储存在DVD型的数组里。一开始的做法是在Movies里直接打印出这个数组,但是发现打印出来的是内存地址(而且地址名字都是一样的),于是检查了一下有没有写错toString,然而并没有。 -
问题2解决方案:后来无奈只能直接在Movies里面声明了一个DVD数组,用于保存原先的数据。后来这样做发现也有一个好处,就是可以直接用那个遍历的方法,把数据都打印出来。如图是过程中写成的代码截图:
如上图,所做的修改主要体现在红色区域:
最上面的那个继承是最开始的那个思路,是想通过继承,把DVDCollection类里的变量等继承下来,把变量和方法都设成了public,数组对象也设成了静态(static)。但是没能解决问题。
后来就采用了第二种思路,就是中间的那块红色区域。这样写就可以直接打印出来了,然后再写一个排序的方法,再打印一遍,对比来看排序的效果,也就是最后修改的结果,对比效果如图:
所以最重要的操作就是写一个按照名字排序的类。就是写成的代码的第三个红色区域调用的selectionsort2方法。对比着例题Contact方法,在DVD类里写下了比较的两个对象,如图:
在Sorting2类里面写下调用上面方法的比较顺序,代码如图:
最终代码如图:
代码托管
上周考试错题总结
-
错题1:
-
错题1解析:这道题其实考察的就是什么是多继承,但是放在实际例子中,就很难去分辨了。多重继承意味着一个给定的类继承了多个父类。而B中的PC要不就是台式的,要不就是笔记本式的;C中的笔记本同时继承了PC和便携式的特点。
-
错题2:
-
错题2解析:我觉得这题选E没毛病啊,Object类不是所有类的父类吗,他也有父类吗?
-
错题3:
-
错题3解析:这个题目是真不知道啊,百度也没找到答案,书上也没找到啊。相同父类的两个子类之间的关系被称为siblings。clone是相同对象的副本,aliases是相同的对象
-
错题4:
-
错题4解析:这一题是真的没话说,课本198页最下面一段。印象中当成了has-a,还以为绝对不会错。。。
-
错题5:
-
错题5解析:这一题错误的原因在于A选项不会翻译,好吧,其实就怪我过于依赖有道翻译
如果直接翻译super class(超类),就不会做错了 -
错题6:
-
错题6解析:。。。没话说,答案是A和B的结合,所以哪个答案都不对,选E。做题的时候没敢选E,就选了一个绝壁对的(书上有原话的),没想到还是被套路了
-
错题7:
-
错题7解析:
根据有道翻译,答案B是错的,选E. -
错题8:
-
错题8解析:任何类都可以扩展,无论是接口、实现接口,还是两者都没有。除非被声明为final。
-
错题9:
-
错题9解析:这道题的出错在于错误地理解了什么是“access”,子类会继承父类的所有变量和方法(包括private),并为变量预留空间,但是子类无法按名引用父类private成员。
-
错题10:
-
错题10解析:子类可以重新定义父类的任何实例数据或方法,通过super.x。
-
错题11:
-
错题11解析:上面一题写错了,这一题肯定是跟着错了,毕竟是同一个题目。。。
结对及互评
-
博客中值得学习的或问题:
- 侯泽洋同学的博客排版工整,界面很美观
- 问题总结做得很全面
- 对于书上的疑惑总会想办法解决它,这种探索的精神值得我去学习
-
代码中值得学习的或问题:
- 对于编程的编写总能找到角度去解决
-
本周结对学习情况
- 20172302
- 结对学习内容
- 第十章内容:多态
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 309/309 | 1/1 | 20/20 | |
第二周 | 269/578 | 1/2 | 18/38 | |
第三周 | 236/776 | 1/3 | 22/60 | |
第四周 | 507/1283 | 2/5 | 30/90 | |
第五周 | 631/1914 | 1/6 | 30/120 | |
第六周 | 529/2443 | 1/7 | 25/145 | |
第七周 | 515/2958 | 1/8 | 25/170 | |
第八周 | 1128/4086 | 2/10 | 50/220 |