面向对象程序设计-前三次大作业总结
-
开篇前言
我个人在这三次大作业中的成绩并不乐观,但是我仍从中学到了许多,在与其他同学的交流中,我也有不少收获,与其他人交流各自的类与方法的设计、逻辑结构、嵌套方式等,都让我受益匪浅,即便成绩并不乐观,我还是有了一些自己的见解,并将之分享出来。 -
正文
- 知识点,难度,题量
(1)题量
三次大作业一共5+4+3十二道题,除去比较难的最后三道题来说,题量并不算多,但是最后三道题的含金量远高于另外12道题,相当于“压轴题” ,也是大作业的主要考察题目。
(2)难度
总体来看,三次大作业难度对于大多数人来说难度并不算太高,毕竟每次都能有满分的同学,但是有一些点对于一些同学来说并不轻松,除去最后三道题目,其余的9道题相对来说比较简单,算是“奖励分”,而最后三道题才是一个分水岭,能够有效的检验同学们的学习状况。
(3)知识点
将最为重要的知识点放在最后来说,是因为这三次大作业的知识点确实不少,具体如下:
①hashmap、List(ArrayList,LinkedList)、数组等一些用来储存元素的“容器“,以及一些其他的泛型。
②六大面向对象原则:
单一职责原则(Single Responsibility Principle,SRP)、
开放封闭原则(Open-Closed Principle,OCP)、
里氏替换原则(Liskov Substitution Principle,LSP)、
依赖倒置原则(Dependency Inversion Principle,DIP)、
接口隔离原则(Interface Segregation Principle,ISP)、
迪米特法则(Law of Demeter,LoD),
虽然六大原则不一定全都会在源码中明显体现,但是我在自己的编写过程中还是在尽力遵守;
③类与对象的使用,这是最基础的部分,必须灵活使用才能写出正确的代码,保证每个类都能实现1-2个功能,才是一个合格且不繁琐的程序;
④正则表达式(Regular Expression,简称Regex或RegExp)的使用,正则表达式在本次大作业也贯穿始终,它是一种用于匹配和操作文本模式的工具。它由一系列字符和特殊符号组成的模式,用于描述和匹配字符串中的特定模式,用于搜索、替换、验证和提取文本数据。它提供了一种灵活和强大的方式来处理字符串,可以用于各种文本处理任务,如数据验证、文本搜索、数据提取、语法分析等,在本次几个大作业中我用来匹配输入信息中的#N、#D等一些提示性字符,以便正常获取输入信息。
(附正则表达式测试工具:正则表达式测试工具)
⑤尽量遵守代码的特性:可读性,可扩展性,可测试性,效率性能,可移植性,安全性,可重用性。 - 源码的设计与分析
(注:由于能力不足,我个人的类与方法设计并没有拿到合适的分数,所以在此使用老师提供的PowerDesigner类图进行分析,并提供解释与心得体会,且个人源码得分略低,便不在此进行展示,只给出一些已解决的bug供查看)
(1)类图及分析:
-
第一次大作业:
第一次大作业只涉及到题目内容,题目数量,答题信息三个具体类,输入及输出都不算复杂,个人认为重难点在于允许乱序输入,即可以不按题号顺序进行输入,这在刚开始对我造成了不小的困扰,在与同学进行交流之后,我了解到可以通过冒泡排序或者选择排序等排序方法根据题号进行处理,这样就可以完美解决允许题号乱序的问题,其余的便是类与方法的合理调用。 -
第二次大作业:
第二次大作业相较于第一次多了试卷信息,一行为一张试卷,一张试卷包括N道题目信息,可输入多行数据,也就是多张试卷,并加入了试卷总分警示,相对来说,试卷总分警示较好处理,只需要在试卷类中加一个计算总分的方法,便可以得到正确的输出,但如何让试卷类与题目类有关联又成了问题,我第一次尝试使用hashmap进行键值对的匹配,可是由于不熟练,并没有得到很好的效果,反而是数不胜数的报错,后来仔细查看了题目要求,无论输入几道题目,只接收#T(试卷信息)前的题目,所以仍然可以使用排序进行处理,并输出合理的结果。这是输入部分代码的展示:
public void printResults() {
for (TestPaper testPaper : testPapers) {
if (testPaper.getTotalScore() != 100) {
System.out.println("alert: full score of test paper " + testPaper.number + " is not 100 points");
}
}
for (AnswerSheet answerSheet : answerSheets) {
boolean found = false;
for (TestPaper testPaper : testPapers) {
if (testPaper.number == answerSheet.number) {
found = true;
int totalScore = 0;
for (Map.Entry<Integer, Integer> entry : testPaper.scores.entrySet()) {
int questionNumber = entry.getKey();
int score = entry.getValue();
String answer = answerSheet.answers.size() > questionNumber - 1 ? answerSheet.answers.get(questionNumber - 1) : "answer is null";
boolean correct = checkAnswer(questionNumber, answer);
System.out.println(questions.get(questionNumber).content + "~" + answer + "~" + (correct ? "true" : "false"));
totalScore += correct ? score : 0;
}
System.out.println(testPaper.scores.values().stream().map(Object::toString).collect(Collectors.joining(" ")) + "~" + totalScore);
break;
}
}
if (!found) {
System.out.println("The test paper number does not exist");
}
}
}
由此可见,仔细读题十分重要。 -
第三次大作业:
第三次大作业相较于前两次,多了一条学生信息和对我个人来说难度有不小的提升,新类的引入与同其他类联系起来成了一个不小的问题,同时删除信息也同样是一个难点,而且还加入了大量针对错误信息的测试点,所以我先整体总结了一下,根据问题描述,我需要设计一个答题程序,它可以模拟一个小型的测试,并根据输入的题目信息、试卷信息、答题信息和学生信息来判断答题结果。首先,我可以定义一些数据结构来存储题目信息、试卷信息、学生信息和答卷信息。可以使用类来表示每个数据结构,接下来是程序大体思路:
① 解析输入的题目信息,将其存储在题目信息数据结构中。② 解析输入的试卷信息,将其存储在试卷信息数据结构中。
③ 解析输入的学生信息,将其存储在学生信息数据结构中。
④ 解析输入的答卷信息,将其存储在答卷信息数据结构中。
⑤ 根据题目信息、试卷信息、学生信息和答卷信息进行判题,并计算得分。
⑥ 输出答题结果。
⑦ 解析输入的删除题目信息,将其从题目信息数据结构中删除。
⑧ 输出删除题目的结果。
⑨ 继续处理下一个输入信息,直到遇到"end"标记。
像这样进行一次大体思路的整理,再进行代码的编写,会觉得清晰许多,剩下的问题便是一些小bug。
(2)bug分析:
(由于测试中bug较多,便在此展示几个典型bug。)
① 非零返回错误,样例:
大多数非零返回错在输入上,输入不符合题目的要求,就会出现非零返回错误,此时大概率要检查输入部分的代码。
②样例:Main.java:60: error: cannot find symbol
int monthsBetween = DATE2.getMonth() - DATE1.getMonth();
^
symbol: method getMonth()
location: variable DATE2 of type CustomDate
解析:这个错误是由于在类型为CustomDate的变量DATE2上调用getMonth()方法而导致的,我认为每个类都尽量加入getter和setter,因为保不准什么收就会用上。
③题目编号与题目信息不匹配,会出现答案正确,但是答案与题号不对应,从而与输出样例不符的情况。
-
踩坑心得
(1)尝试使用哈希映射(hashmap)来进行键值对的匹配,但由于不熟悉操作,导致出现了许多错误,所以我建议在不熟悉一些语句的使用下,还是使用个人比较了解的语句进行编写,不能图方便而使用不熟练的代码,或者花一部分时间仔细钻研一下有利于编写的方法。
(2)正则表达式的使用,正则表达式在刚入门时使用无疑是一把双刃剑,一方面,它是一种强大的工具,可以帮助我们快速有效地处理文本数据。另一方面,错误的使用正则表达式无疑会极大增加作业的完成效率,甚至会让自己感动到困惑和挫败,但我还是建议精通正则表达式,因为它真的很方便。 -
改进建议(个人代码)
(1)简化逻辑和提高可读性: 目前代码中存在很多嵌套的条件语句和循环,使得代码难以理解。可以考虑将一些复杂的逻辑分解成更小的函数或方法,提高可读性和维护性。
(2)学习一些新方法的使用,例如在数据结构上,使用更有效率的哈希表、列表、数组等数据结构来存储和管理信息。
(3)命名规范:遵循命名规范,例如类名使用驼峰命名法,变量名使用有意义的名称,增加代码的可读性。
(4)注释和文档: 在关键的地方添加注释,解释代码的功能和逻辑,以及方法的作用和参数说明,有助于其他人理解和维护代码。
(5)代码重构: 一些代码块可以进行重构,例如提取重复代码成为单独的方法或函数,以提高代码的重用性和可维护性 -
总结
(1)综合性总结:
总而言之,这三次大作业让我学会了如何使用引用变量与对象实例之间的关系,并了解了方法调用时引用类型参数的传递过程,如何分析问题写出面向对象的代码。蔡轲老师讲课风趣幽默,同时也能很好的传授知识给我们,课堂氛围轻松无压力,课堂作业也在能力范围内,每节课都会讲一些语法和方法的使用,除此之外还会引导大作业的进度,老师能够认真倾听我们的不解之处,并及时给予解答,也算是一种教学相长。
(2)改进建议:
①课上及课下组织方式:建议教师在课堂上采用多样化的教学方法,如讲解、示范、讨论、小组合作等,以激发学生的兴趣和参与度。同时,在课下可以提供一些额外的学习资源和资料,供学生进一步学习和拓展。
②建议在作业设计上,适当控制作业的难度和量化,以免给学生造成过大的压力。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 易语言 —— 开山篇
· 实操Deepseek接入个人知识库
· Trae初体验