面向对象第一单元学习体会与总结

会有一股神秘感。 提交于 2020-05-02 06:35:22

 摘要:不知不觉已经来到了大二的下学期,本学期我们又喜迎两大魔鬼课程——面向对象与操作系统,而这篇我在博客园上的开园之作便是OO的第一次博客作业辣。对于OO,我最最初的认识是通过中国大学慕课上的翁恺老师开设的面向对象课程,那时只是对Java与面向对象有了一个朦胧的认识,而回到学校并经过第一单元的学习之后,我便深刻体会到面向对象与过往的面向过程的巨大不同,接下来就通过对第一单元学习的总结来记录下这份感受。


 

1、作业分析:

第一次作业:

  

结构分析:

  第一次作业要求是对只包含幂函数的一个多项式进行求导。由于这次的作业的逻辑不是特别复杂,再加上自己并没有从面向过程的思维中跳出,出现了一个类莽完的情况(尴尬)。对表达式的解析由于寒假pre_homework的帮助得以利用正则表达式轻松解决,然而依旧尴尬的是我的判断wf方法正是助教们极力反对的大正则。接下来提取各项要素我使用的是正则中group()的分组提取方法,并用HashMap存储,过程也并不复杂。反而是最后求导并输出的环节需要处理不少细节。不出意外,大部分的复杂度都集中在了求导函数中。

Bug分析:

  如前所说,第一次作业我在强测中未被测出bug,但在互测中被爆了一个系数为0的时候输出漏了符号的错误。在自己测试得时候完美的略过了这种情况。。。

 

第二次作业:

 

 

 

结构分析:

  第二次作业引入了简单三角函数,并增加了他们与幂函数之间的乘法规则。这次的类图显然复杂了不少(把一大把正则的Pattern和Matcher丢到了属性里去是一个重要原因)。此外,这次求导部分的耦合度有所减轻,但是三角函数的简单合并与输出部分仍然十分复杂。原因应该于ArrayList的频繁遍历有关。

  我一开始很想用助教提示的以自建对象作为键的HashMap作为数据的组织方式。但害怕自己的hashcode和equals会出错。。便还是用了最稳的ArrayList。我将表达式抽象为项的ArrayList,再将项抽象为基本元素的ArrayList。这一次我试着尝试了让sin(x),cos(x),x^..都继承自抽象类SimpleTerm,使得对每项求导时,只需要对SimpleTerm的对象数组进行两重循环的求导便可,算是实现了一个多态吧。

  我认为这种组织形式虽然在这道题上关于化简时不及多对一的HashMap,但当函数种类增多时,我需要做的只是增加SimpleTerm的子类,应该是便于扩展的,事实上由于我的类之间安排的不是很合理,导致了第三次作业还是得从头来过。

  在解析输入时我仍然使用了大正则对整体做合法性判断,并对项逐个进行正则匹配。。怎么说呢,这次这样做仍能勉强存活下来。。但很快我就会体会到之后的作业会面临多大的障碍。。

Bug分析:

  由于我的两个ArrayList的冗杂设置,,使我的求导过程麻烦了不少,也让我头脑昏昏沉沉的写出了几个致命的bug。。比如在强测中就被测出自己的符号解析在两个以上时会判断错误(完全漏了这项工作),以及互测中发现在空格错误上漏考虑了一种情况。只能心急吃不了热豆腐吧,不多花点时间思考便是这个后果。在求导部分没有影响结果的bug出现。

 

第三次作业:

  

结构分析:

  第三次作业难度瞬间上了一个台阶:因子多了多项式因子与嵌套因子。但仔细一想,若能将这些因子妥善分离,第二次的思路应该还是可以照搬。多项式因子与嵌套因子在我看来最适合用递归解决。所以最难的部分便成了输入判断。。。我折腾了半天,最后用了从左到右扫描加递归判断的方法。另外,这次我采用了指导书的建议,给嵌套因子,幂函数因子,乘法项都建了一个求导接口,使得乘法求导形成了与第二次类似的一种多态。从度量分析图中可以看出,求导部分的耦合度仍然很高,这是由于我在表达式求导中引入了其它所有求导法则类的原因。

Bug分析:

  这次我在强测中未被测出bug,但在互测中被测出了没有完善的判断符号数因子的符号与连接项之间的符号的错误(这里就要吐槽一下强测确实不怎么强了:))不过还好也是两三行就能解决的事。


 2、作业总结  + Test Summary

  第一单元的作业,在我看来是一个让我从面向过程向面向对象的过渡过程。三次的作业,都可以抽象为“输入的合法性检测”, “表达式的解析与项建立”,”表达式求导“这几个可以互相独立的过程。虽然把大量数据都设置为private并且为他们加上get与set方法很是头痛,但仔细斟酌后还是能体会到这样做的好处。各种类之间由于诸如此类的封装操作,让彼此之间只能通过特定的接口进行沟通,这样的设计在解决某个问题时或许不如面向过程来的快,但是在可能的扩展与维护上,这样能让我们对代码的修改降到最小。”万物皆对象“的哲学,感觉应该算是入了点门吧。

  关于测试,在互测中我做的是很笨的人工找bug(而且经常发现不了别人的bug)。自测时一般对每个功能独立的类用main进行简单的单元测试,并把比较巧的测试样例也用在互测中。比如在第一次测试时自己经历过爆栈,于是也拿超长的数据去测试他人的程序。今后打算学习一下用脚本进行批量测试。


3、接口与抽象类

  在第二次作业中用到了抽象类,在第三次作业中用到了接口。写作业时对他们区别与共性还是非常不了解的,现在也想在这里把自己目前所认识到的东西记录一下。

  抽象类是一种高层次的抽象,例如学生与老师虽说是两种区别很大的类,但都可以继承自”人“这一祖先类。抽象类中可以封装数据与方法,其中的抽象方法的实现在继承他的子类中。例如”人“具有名字,年龄等属性,都有”自我描述“这个方法,后者需要有”什么样的人“来实现。那么,为什么要使用抽象类而不设计一个一般的”人“的父类?在我看来,这是因为类似于”人“这样的抽象并不会被我们去实例化一个对象,即我们在解决问题时用到的都是”人“的子类,而一般不会想真正去new一个Person对象。与之对应的,我们会需要从这样的子类中去提取一些公共信息。例如我在第二次作业中使用的抽象类”SimpleTerm"代表简单因子,他们都具有power属性,但他们的求导需要在具体的子类中去实现。

  对于接口这个概念,我在查阅资料与听取助教与大佬同学的讲解之后也有了个大概的了解。与抽象类相比,他们都会在内部有一些需要由继承或实现了它们的类来实现的抽象方法,从这一点上看来它们能起到相似的作用。但其实二者有着很大的区别。从用法上来看,抽象类只支持单继承,而一个类却可以实现多个接口。抽象类可以封装具体数据而接口只能定义常量。从具体意义上看,继承抽象类是一种“is a"关系的体现,即”学生是人“,”幂函数是因子“,前者会继承后者的所有数据和方法。接口是一种行为抽象。引用助教老师给过的例子:鸟会飞,飞机会飞,于是可以设计“飞”这一接口,但毫无疑问的是飞机和鸟不会有一个共同的父类。。继承使得新的类在原类得基础上有了更多的特殊性,可以通过更少的代码扩展更多的功能,同时实现从属上的多态。而接口说明一系列类都能提供某种形式相同的服务,为类的行为定义提供了很大的灵活性,实现了行为上的多态。

  老实说,在我的第一单元的作业中,抽象类与接口的不同并没有得到严格的体现。希望能通过接下来的学习对这两个概念有更深的理解。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!