OOP前三次作业总结
一、前言
在开始OOP学习之前,我从未了解过什么是面向对象编程,想当然的认为OOP是像从前学习C一样的编程逻辑(即面向过程编程),但在真正开始学习OOP之后,我了解到了以往面向过程编程的局限性与不便利性。
而OOP却具有以下特点
1、封装:隐藏对象的属性和实现细节,仅对外提供公共访问方式,将变化隔离,便于使用,提高复用性和安全性。
2、继承:提高代码复用性,继承是多态的前提。
3、多态:父类或接口定义的引用变量可以指向子类或具体实现类的实例对象。提高了程序的拓展性。
大大提高了代码的运行稳定性。
二、三次作业内容分析
1.第一次作业
本次作业的主要内容是对java语言的基础应用,并未要求涉及面向对象编程的内容,也未对复杂度进行要求
唯一值得一提的是 7-8 判断三角形类型
该题目主要考察的是能否正常的满足题目的要求,在解题时,驱动我的动力是如何达到题目检查点的要求,而非在提交代码前对题目要求进行全面的考虑,导致在我解决这道题目时进行了很多次的提交,以此通过所有的检查点,但从题目难度的角度来说,这道题目本身的难度不大,稍微对代码进行修改就能顺利的通过检查点。
上图为该题目的代码分析,可以看出在学习初期并未对代码的复杂度做过考虑,也未使用面向对象编程的编写逻辑,此处故不进行详细分析。
尽管此次作业的难度并不是很大,但这次作业的意义却十分重大,通过完成此次作业,在后续的学习中,每当再次翻阅这次作业的记录,能更加了解到面向对象编程的便利性,使我更加深刻了解到过去编写代码方式的局限性
2.第二次作业
本次作业依然是检验java语言的正确使用,同样并未要求使用OOP的编程逻辑,故该次作业同样不对复杂度进行详细分析
在解决7-1时,为了满足题目的需求,同时也是为了提高java这门编程语言的熟练度,我首次学习并使用了java中所自带的方法String.substring()及Integer.parseInt()以此达到截取字符串子串,进行字符串整数化及数制转化的效果
如下图
代码测试效果如下
值得一提的是,局限于代码编写的目的是为了完成题目所给出的需求,从源代码可以很容易看出,该代码对输入数据的内容具有强制要求,仅对长度做出了限制,但并未对非法数据进行处理,如下图
题目7-3、7-4、7-5对解题方法有一定的要求,所考察的是解题者是否能正确的理解java所自带的日期类代码的内容,并要求了解题者在Main类中必须含有规定的方法
在题目7-4中,要求的是在不使用Java中和日期相关的类和方法的同时,输入年月日的值(均为整型数),输出该日期的下一天。
在该题目中,可以利用在7-3中编写的方法,以此快速判断输入日期是否为闰年,源码如下
在考虑解题过程时,除了要满足输入日期的下一天,还需要考虑一些特殊情况,如:
(1)平年闰年的2月29日
(2)该月的总天数
(3)输入日期的下一天是否跨年
(4)输入日期是否合法
通过分析问题的需求,对主类的静态方法进行修改,最终达到题目的要求
测试结果如下
在题目7-5中,相较于题目7-4中输出该日期的第二天,本题将要求修改为了输出该日期的前N天,这就意味着除了在考虑原先的特殊条件上,还需要考虑N的正负值,日期是否跨年,日期是否跨月,日期计算后是否与闰年有关等
与作业一的情况类似,由于未使用面向对象编程思路进行优化,程序的圈复杂度十分感人,仅仅只是为了完成题目要求而编写代码
测试结果如下
3.第三次作业
从本次作业开始,我才真正开始学习如何以面向对象编程思想来进行解题,并在编写程序中学会了编写类,并创建对象来完成对应的方法
7-1 创建账户类Account
本题的要求安是设计一个名称为Account的类,在设计之前,考虑到面向对象设计思想,我选择了专门创建一个名为Account的对象进行后续操作
结合课上老师讲的内容,在创建Account类时,我定义了public Account (int Id,double Balance,double X) 以此定义对象的初始值
同时,我将id,balance,annualInterestRate等变量设置为private型,并通过编译器脚本生成了getter与setter,以此防止直接对变量进行操作
由于该代码使用OOP编程,相较于前两次作业,圈复杂度有了明显的优化
7-2 定义日期类
在本题中,需要定义一个类Date,包含三个私有属性年(year)、月(month)、日(day),且均为整型数,同时不允许使用相关日期的类与方法
在分析之后,可以得知该题目的要求与作业二中7-4的要求十分相似,唯一不同的是不像作业二一样不对类做要求, 于是我在本次作业中,对题目要求中所需求的功能进行了拆分,并与7-1一样设置了相关private变量的setter与getter
由于闰年的二月与平年的二月的差异,我设置了两个数组,先通过isLeapYear()判断是否为闰年,再以此返回的bool值选择对应的数组,最终取出数组中对应的数字,表示该月的总天数
源码截图如下
定义类如下
圈复杂度分析如下
由上图可以看出,由于在checkinoutValidity()中的if-else量过大,导致圈复杂度依然保持着9的数量,使程序不是那么简单易懂,由于判断日期是否合法的条件过多,导致圈复杂度不容易降低,故难以对该方法进行修改
7-3 一元多项式求导(类设计)
在解答该题目的时候,可以明显感觉到难度相较于以往所有题目有着巨大的提升,不仅仅要使用面向对象思想进行程序设计,同时还要自学并使用正则表达式,在正则表达式的使用中,我深深感觉到了这东西的强大,以及它在字符串方面的广泛应用
该题目的要求为编写程序,实现对简单多项式的导函数进行求解,考虑到在输入数据时,用户可能会在输入时输入空格符,我选择了使用String.replace()方法,将所有“ ”替换为了“”,即将所有空格符清除,以此满足输入数据为标准格式,便于后续数据的处理
为了保证字符串的多次修改,也为了防止创建过多的字符串,我选择了使用ArrayList<String> 来创建可变字符串,以此来记录符合“*x”前后的所有数字与符号,并将其转化为整型数,以此进行计算。
在调试过程中,发现若输入数据首位为负数,会导致首位结果出错,额外输出一个“+”,于是我选择增加对输出时数字前的符号进行判断,选择是否打印“+”
源码截图如下
调试结果如下
定义类如下
圈复杂度截图如下
可以看见,为了提取字符串“*x”前后的所有符号与数字,在derivation.Calculate()中进行了大量的判断,导致圈复杂度达到19之多,若要进行修改达到降低圈复杂度的目的,可以将该方法中的if进行拆分,为不同的情况下的判断专门编写一个方法,以此达到使代码简单易懂的效果
三、踩坑心得
通过一个多月的学习,我深刻了解到了OOP的便利性,相比于先前的编程方式,面对对象思想不仅仅能让代码阅读者更加清晰明了的了解到代码的作用与意义。更重要的是可以让代码编写者不那么容易把自己写蒙圈
与其跟着检查点走,不如在开始进行设计前,先考虑程序可能会遇见的特殊情况,在自我调试中对代码进行修改,这样不仅仅可以让设计思路更加简单易懂,同时在优化代码时也更加便捷,不那么容易写出屎山代码
四、总结
本次作业,我个人进步最大的地方是完成了从原先的面向过程编程到面向对象编程的转变,并在实践中学会了对代码复杂度及程序类图的分析,并以此为基础,为后续的课程学习打下了基础,使我能更好的学习OOP的编程逻辑。