OO第一单元总结

写在开头:因笔者能力有限,分析不够到位,知识不够全面,本文可能纰漏颇多,指导意义不强,见谅!

第一次作业

这相当于是第一次做大型一点的oo作业,面向对象的思想很不成熟(当然现在也是一样),我的代码仅仅停留在面向过程的层面,采取的是“一main到底”的方法,改了好多次好不容易改过了,互测还被砍了好多刀(我太难了),以下是我的写法、想法,一点小经验,也可以说是大家的错误示范,希望不要跟我这样写,不然后面的作业会很痛苦,甚至会gg的。

第一次作业要实现的是高中很熟悉的多项式的求导,当然手算很简单,但是怎么用代码来表示呢,这考察了我们的动手能力以及抽象能力,其实我刚看到这个题,脑子里想的就是一种面向过程的想法,也就是与C语言类似,我可以只写一个Main,然后在里面把所有功能都实现,比如先解析多项式,把项全都提取出来,存到数组里,最后进行求导之后再按顺序输出,看似没有问题,但是写出来后肯定性能会很差,也会被大佬一个测试数据就崩掉,题目要求缩小数据长度,那么怎样缩小数据长度呢?可以通过新建一个Term类,来保存我们应该有的信息,比如指数和系数等,在这个类里面实现每个类应该具备的功能,比如求导,那么如此一来,我们在Main里面就只需要先解析表达式,把多项式分成若干项,再把他们实例化为一个Term对象,存到对应的比较好用的数据结构Hashmap里面,这样,我们可以实现指数相同的项的合并,从而减小输出的长度,实现一定的优化。

我并没有对第一次代码进行重构,也就是说应用的是面向过程的方法,我另外写的方法仅仅只有一个Term的构造方法,这种写代码的方式显然是不可取的,我自己也为此付出了惨痛的代价,望大家引以为戒。

在这次作业中,我们方便的用到了一个处理表达式的方法,即正则表达式的应用,应用正则表达式不仅可以很好的解析多项式,看是否符合我们需要的结构(若不符合输出“WRONG FORMAT!”),还可以把我们需要的系数和指数分别提取出来,并保存到Hashmap里面去,这样处理的效率比手动操作是要高的,而且不容易错,因此正则表达式应好好学习,熟练使用,在后续作业中也可使用(我没别的办法只能用)。

 

 

然后需要注意的是,这次作业的bug的点呢,主要有一个BigInteger的问题,即系数和指数可能会超过long的范围,那么我们用普通的int肯定是不行了,这时我们要用到的就是BigInteger,大家可以自行百度查阅资料,看过之后发现,它的用法与int等类型大不相同,甚至与普通的常数,如0比较大小都得先把0转换为BigInteger,然后再利用自带的CompareTo方法进行比较,虽然比较烦,看上去也比较吓人,但是必须得用,不然被他们卡死了这几个测试点,就会必没。

还有一个比较好的想法呢,就是输入完,用正则表达式判断完格式的正误(主要是+-号和空白符位置)之后,若为正确的表达式,则可以把空白符全部去掉,

 

然后也可以通过同样的方法,把多项式中所有的“**”都换成“^”,这样在之后写正则表达式时可能会好处理一些,也不容易与乘号*混淆,最后全部处理完之后呢,输出的时候,再把"^"给换回"**"即可,这就是一个变换符号使得思路更清晰的过程。

 第二次作业

第二次作业增加的要求是,三角函数sin和cos的求导,这一次呢,还没有加入第三次的表达式因子嵌套功能,所以实现并没有那么的困难(指对于面向对象选手而言),作为上一次作业忠实的面向过程选手,这次选择一莽到底,结果代码水平不够,写的代码丑陋不堪。如果还是想要面向过程的话,并不是不可,因为与第一次作业相比,改变的是正则表达式的写法,因为解析的方法不一样了,但是假如还是使用一个Term类的话,显然是不够用了的,因为它适用于实例化幂函数的对象,对于三角函数,我们就应该重新分别写两个类Sin和Cos,这样才可以继续进行下去,然后分别在各自的类里,写好构造方法,写好各自的求导方法,当然也还是可以采用面向过程的办法,但是假如这次还是面向过程的话,也许这次过了,但是第三次作业的那种嵌套表达式,重重递归,估计会比较困难,所以劝大家尽早训练面向对象思维,不要最后再来痛苦重构,那么接下来有一些我的小经验分享以及看看面向对象选手的写法。

 

 

 

 这张图里的类的关系一目了然,这次作业采取面向对象的方法的话,我们会采用继承的办法,即用子类去继承父类,子类包含而不局限于父类的功能,子类也可以去覆写父类的方法,从而实现个性化的功能,这种方法是后面的学习中所必须使用的,当然还有一些其他的想法,如多态等,我们Func是最基本的类,把每个类应该包含的公共的方法写到里面,比如求导,加和乘等,下一层为BasicFunc、MultyFunc和AddFunc,其中MultyFunc处理的是多项式中乘法的求导,而AddFunc自然面对的就是加法方面,接着往下,BasicFunc又细分为多个子类,来处理各种类型的求导的问题,比如Sine处理的就是sin的求导以及式子的相关问题,Cosine相对应的就是cos的相关问题,写完了Sine类,再写Cosine类时,很多地方思路完全一致,改一点即可,最难实现的是Power类,因为要处理与指数相关的较为复杂的问题。最后,所有功能在MainClass中实现即可。

这次作业呢,还是使用了正则表达式来解析多项式,与第一次相比,错误格式的判断加了一些内容,比如sin,cos这几个字母间不能有括号,sin,cos括号里面不能有幂函数等,而对于其他情况的错误格式,采取的办法也还是一样,用正则表达式判断后,如果不符要求,则输出“WRONG FORMAT!”,不然则进行下一步的解析,这里我看有的大佬的办法是采取有限状态机来处理括号等的问题,我采用的办法还是正则表达式,使用正则表达式的时候情况一定要考虑全面,不然容易出错。

这次需要注意的是,幂函数(注意是幂函数!!)的指数的绝对值不大于10000,如果没看到这个要求,就gg了,当然看到了,如果写的时候分类没分好,把幂函数和三角函数的指数放一块儿处理,也可能会gg。

实现这些以后,我们来看看这个代码的复杂度的分析,上图。

 

 可以看见在MainClass和Func类中,Average operation comlexity还是比较高的,所以代码还有很多可以改进的地方,但是这位大佬的面向对象的思想可以借鉴,而且这种通过各种继承和覆写,使得程序的思路变得清晰,结构严整,debug的时候呢,容易分析到是哪个class的哪一段出了问题,是方法出了问题还是其他问题,所以我们要学习这种思想和结构性。

最后值得一提的是工厂模式的运用,如果熟练的掌握工厂模式,对自己每次作业代码迭代时是很有用的,因为你的代码的可扩展性很强。

以上即为我的一些拙见!

 

 

 

posted @ 2020-03-21 19:54  mlbz  阅读(181)  评论(0编辑  收藏  举报