OO第四-第六次作业总结
1、前言(对三次作业的总结)
这三次的作业分别考察了:1、对继承的理解与使用、同时使用封装。2、对多态的理解与使用、同时使用封装。 3、正则表达式的使用、以及接口的使用、继承与多态的使用。
题量:相差无几,考验对日常时间的使用。
难度:逐级递增,有三个题目未能在规定的时间内完成。
2、设计与分析
1.题目集4(7-2)、题目集5(7-4)
根据老师对题目做出的要求,7-2需要我们完全使用继承,Year是最大的父类,DateUtil是Day的子类,Day是Month的子类,Month是Year的子类。

所以便有了
而7-4则是使用多态,DateUtil是父类,除主类之外都是其子类。

于是便有了:

而对于多态与继承之间的优劣,我的想法是:在实用性上,多态完胜继承,无论是在复用性还是在思路的清晰程度以及可读性上。但事与此同时,多态是建立在继承上的,如果不能有效的使用继承给我们带来的延展性,自然也无法有效的使用多态带来的更多红利。
在代码细节方面,在改变了因为父类的改变而不得不改变的代码后,整个代码量便减少了50行。而且少了因为多重继承而需要的诸如:
public boolean compareDates(DateUtil date){ if(day.getMonth().getYear().getValue()>date.day.getMonth().getYear().getValue()){ return true; } else if(day.getMonth().getYear().getValue()==date.day.getMonth().getYear().getValue()&&day.getMonth().getValue()>date.day.getMonth().getValue()){ return true; } else if (day.getMonth().getYear().getValue()==date.day.getMonth().getYear().getValue()&&day.getMonth().getValue()==date.day.getMonth().getValue()&&day.getValue()>date.day.getValue()){ return true; } else { return false; } }
这个方法中出现的~~day.getMonth().getYear().getValue()~~这种东西,这种东西我认为对日后的维护非常不友好,鲁棒性较差。
2.题目集4(7-3)、题目集6(7-5、7-6)
这三题是针对图形类问题的递进式考察,从对封装性以及继承的简单考察到继承与多态再到最后的接口继承。
7-3是我在作业中第一次触及到继承,所以给我造成了一点麻烦。对于7-3我的思路是:先创建父类Shape,然后再一个一个写其子类的属性以及方法。

7-5的思路与7-3有很大的差别,更加的考验对继承以及多态的理解,难度也提高了很多。这题需要我们先建立一个合理的父类Shape而不是7-3中只有一个方法的Shape。

在建立了父类后,我们需要考虑到因为题目的要求很多,而且测试点很复杂,也就需要一个更加健壮的父类来减少我们写子类的时候的工作量。
同时增加子类中的方法来增加代码的鲁棒性,来通过题目的各种特殊情况的考验。
7-4因为引入的接口这个概念,使得我需要重新审视一遍这个写过很多遍的题目,因为在写这个题目的时候我们还没有上关于接口的课,所以在多番查找资料过后最终形成了这个架构(看起来就很低级):

我对这题的思路也就是创建一个合适的接口,然后再其子类Circle中完善题目所要求的一切功能,并且不断地调整,最终使其可以通过PTA的考验。
3.对三次题目集中用到的正则表达式技术的分析总结
正则表达式可以极大的减少我们在分割字符串的时候的时间,前提是你能考虑好题目需要我们分割的所有情况,不然如果你的注释写的不好的话会造成事倍功半。比如:
题目集五7-4中:
public class Main { public static void main(String[] args) { java.util.Scanner input = new java.util.Scanner(System.in); String []strings={"abstract","assert","boolean","break","byte","case","catch","char","class","const","continue","default","do","double","else","enum","extends","false","final","finally","float","for","goto","if","implements","import","instanceof","int","interface","long","native","new","null","package", "private","protected","public","return","short","static", "strictfp","super","switch","synchronized","this","throw","throws","transient","true","try","void","volatile","while"}; Keywords []keywords=new Keywords[53]; for (int i=0;i<53;i++){ keywords[i]=new Keywords(); keywords[i].setWord(strings[i]); } String s=""; String a=input.nextLine(); while (!a.equals("exit")){ s=s+a+'\n'; a=input.nextLine(); } if (s.equals("")){ System.out.println("Wrong Format"); return; } s=s.replace("["," "); s=s.replace("]"," "); s=s.replace("-","a"); s=s.replace("*","a"); s=s.replace("/","a"); s=s.replace("+","a"); s=s.replace(">","a"); s=s.replace("=","a"); s=s.replace("!","a"); s=s.replace(":","a"); s=s.replace("\\","a"); String[]s1=s.split("(\\/\\/.*\\n)|(\\/\\**(.*?)\\/)|(\".*\")"); s=""; for (int i=0;i< s1.length;i++){ s=s+s1[i]; } s=s.replaceAll("(\\%|\\.|\\+|\\-|\\*|\\/|\\{|\\}|(\\()|(\\))|(\\;)|\\'|\"|\\<|\\>|\\=|\\[|\\]|\\||\\&|\\!|\\?|\\:|\\,|\\s+)"," "); //\%|\.|\+|\-|\*|\/|\{|\}|(\()|(\))|(\;)|\'|"|\<|\>|\=|\[|\]|\||\&|\!|\?|\:|\,| String[]b=s.split(" "); for (String value : b) { if (value.equals("")) continue; for (Keywords keyword : keywords) { if (keyword.getWord().equals(value)) { keyword.addAppear(); break; } } }
通过多次使用正则表达式并且合理分析了所有可能出现的情况后,大量的减少了相比不使用正则表达式的情况的工作量。
而在题目集六的前四题中,正则表达式的用法大同小异,都是通过各种符号将字符串分割,获得正确的答案。
4.题目集5(7-4)中Java集合框架应用的分析总结
这题考验了我们对java集合框架中ArrayList的理解与使用,因为输入的不再是以前的短短几个数字或者是字符串,而是一段拥有大量java关键字的整篇代码。我们需要将数据输入链表然后用正则表达式进行切割,最后输出。
3、踩坑心得
1.
public boolean TheHigherYear(DateUtil first,DateUtil next) { if (first.getYear() > next.getYear()) return true; else { if (first.getYear() == next.getYear()) { if (first.getMonth() > next.getMonth()) return true; else { if (first.getMonth() == next.getMonth()) { return first.getDay() > next.getDay(); } else return true; } } } return false; }
在提取最大的年份的时候傻乎乎的以为可以分开比较年月日的大小就可以,忽略了这是三个连贯的数字。
2.
public boolean checkInputValidity(int year,int month,int day) { if (month == 4||month == 6 || month == 9|| month == 11) return day <= 30; if (isLeapYear(year)) { if (month == 2) { return day <= 29; } } else { if (month == 2) { return day <= 28; } } return year >= 1820 && year <= 2020 && month >= 1 && month <= 12 && day >= 1 && day <= 31; }
在做日期类聚合二的时候一直有一个测试点过不去,最后在不断的调试下发现是二月没有完全分清楚情况,于是将二月份单独提取出来进行讨论。
3.
public DateUtil getNextNDays(int n) { while (n > 366) { if (isLeapYear(year+1)) { n -= 366; } else { n -= 365; } year += 1; } if (n > 0) { for (int i = 0; i < n; i++) { day++; if (day > getDayOfMonth(year, month)) { day = 1; month++; if (month > 12) { month = 1; year++; } } } return new DateUtil(year, month, day); } return new DateUtil(year, month, day); }
写这题的时候一直出现运行超时的情况,所以将一天一天的不断循环改为如果年月日之间有一定的间隔便将年月日分开计算而不是一天一天算。
4.
int a = in.nextInt(), b = in.nextInt(), c = in.nextInt(); if (a<0||b<0||c<0){ System.out.println("Wrong Format"); return; }
在写这段的时候经常丢三落四,考虑情况不完全,题目的要求很严格导致在后期调试的时候出了很多错误。
4、改进建议
1.

7-6 实现图形接口及多态性 中最近系统的学习到了接口的定义以及具体的使用,发现可以对其进行结构上的不少优化,比如将Rectangle中的不少方法写的更加合理。
2.
public static void main(String[] args) { Scanner in = new Scanner(System.in); ArrayList<Shape> shapes = new ArrayList<>(); ArrayList<Double>area=new ArrayList<>(); int a = in.nextInt(), b = in.nextInt(), c = in.nextInt(); if (a<0||b<0||c<0){ System.out.println("Wrong Format"); return; } for (int i = 0; i < b; i++) { Rectangle rectangle = new Rectangle(); rectangle.setLength(in.nextDouble()); rectangle.setWidth(in.nextDouble()); if (rectangle.validate()) { shapes.add(rectangle); area.add(rectangle.getArea()); } else { System.out.println("Wrong Format"); return; } } for (int i = 0; i < c; i++) { Triangle triangle = new Triangle(); triangle.setSide1(in.nextDouble()); triangle.setSide2(in.nextDouble()); triangle.setSide3(in.nextDouble()); if (triangle.validate()) { shapes.add(triangle); area.add(triangle.getArea()); } else { System.out.println("Wrong Format"); return; } }
7-5 图形继承与多态 中main方法结构过于臃肿,可以将不少东西通过建立一个新的方法来增加可读性,使代码写起来更加方便。
5、总结
在这次的学习过程中,我学到了不少关于封装、继承、多态以及接口的知识,熟练了之前一直被我嗤之以鼻的正则表达式(熟练后还真挺好用的),我总结一下我认为的优点:
封装的好处:
(1)良好的封装能够减少代码与界面耦合。
(2)类内部的实现可以自由修改的。
(3)类具有清晰的对外接口(确定内容的访问属性,是公有还是私有;字段是只读、只写或者是可读可写等)
继承的好处:
(1)继承使得所有的子类的公共部分都放在了父类中,使得代码得到了共享。提高了代码的重用性,避免了重复。
(2)继承可使得修改或扩展继承而来的实现都较为容易
(3)使类与类之间产生联系,为多态提供了前提
多态的好处:
(1)增加了代码的维护性以及可拓展性。
同时我希望老师能适当的放宽作业的提交期限,因为有些时候时间实在是不够。对于老师上课所讲的我都感觉非常的深入而深刻,对我学习java,查漏补缺方面
都有很大的作用,同时我希望老师实验课的时候能多观察我们编程时碰到的难点,然后有针对性的提出建设性的建议。
浙公网安备 33010602011771号