oop作业4到6次总结
1.前言
这三次pta作业,我认为第四次属于过渡,难度还行,从第五和第六次pta作业开始,难度就明显有一个直线上升。题量也比较大。虽然第六次作业只有一道题,但是一道题拥有1700行+的代码量,难度和前面两次完全不能比。第四次作业的知识点主要还是覆盖在面对对象的封装性上;第五次作业就让我学会运用正则表达式来判断数据的合法性,还有类中的关系,如:依赖、继承、聚合、关联;最后一次作业感觉知识点就很全面了,因为它要求我们做出一个相对完整的点菜系统,其中的类就有很多,主函数中更有其他的复杂的判断需要编程。总之感觉第六次作业还是比较难的。
2.设计与分析
第五次作业的第五题和第六题功能相似,但是结构明显不同,感觉出了C语言和Java明显的区别,对象和对象之间可以有不同的关系,怎么合理的设计对象与对象之间的关系感觉是学好Java的必修课。


点击查看代码
class DateUtil{
private Day day;
public DateUtil() {
day = new Day();
}//无参构造
public DateUtil(int d, int m ,int y) {
day = new Day(y,m,d);
}//含参构造
public Day getDay() {
return this.day;
}
public void setDay(Day d) {
this.day = day;
}
//set,get创建方法
public boolean checkInputValidity() {
if(getDay().getMonth().validate() && getDay().getMonth().getYear().validate() && getDay().validate()) {
return true;
}else {
return false;
}
}//检验数据合法性
public boolean compareDates(DateUtil date){
if(date.getDay().getMonth().getYear().getValue() > day.getMonth().getYear().getValue()) {
return false;
}else if(date.getDay().getMonth().getValue() > day.getMonth().getValue() ){
return false;
}else if(date.getDay().getValue() > day.getValue()) {
return false;
}else
return true;
}//比较两个日期的大小
public boolean equalTwoDates(DateUtil date){
if(this.day.getMonth().getYear().getValue() != date.day.getMonth().getYear().getValue())
return false;
else if(this.day != date.getDay())
return false;
else if(this.day.getMonth().getValue() != date.day.getMonth().getValue())
return false;
else
return true;
}//判断两个日期是否相等
public String showDate(){
return this.day.getMonth().getYear().getValue() + "-" + this.day.getMonth().getValue() + "-" + this.day.getValue();
}//日期格式化
public DateUtil getNextNDays(int n){
int i = n;
for(;i > 0;i--)
{
int days = day.getValue();//用一个数据记录天数
day.resetMax();//把天数改为最大值
if(days == day.getValue()) {
day.setValue(days);//把天数赋回
if(day.getMonth().getValue() == 12) {
day.getMonth().resetMin();
day.resetMin();
day.getMonth().getYear().yearIncrement();
}
else {
day.getMonth().monthIncrement();
day.resetMin();
}
}
else {
day.setValue(days);//把天数赋回
day.dayIncrement();
}
}
return this;
}//求下n天
public DateUtil getPreviousNDays(int n) {
int i = n;
for(; i > 0; i--)
{
if(day.getValue() == 1) {
if(day.getMonth().getValue() == 1) {
day.getMonth().getYear().yearReducton();;
day.getMonth().resetMax();
day.resetMax();
}
else {
day.getMonth().monthReduction();
day.resetMax();
}
}
else
day.dayReduction();;
}
return this;
}//求前n天
public int getDaysofDates(DateUtil date) {
int t = 0,t1 = 0;//给定两个整形记录相差的天数
if(day.getValue() != 1) {
t = t + day.getValue() - 1;
day.resetMin();
}//把天数归一
while(true){
if(day.getMonth().getValue() != 1) {
day.getMonth().monthReduction();
day.resetMax();
t = t + day.getValue();
}
if(day.getMonth().getValue() == 1)
break;
}//把月归一
while(true) {
if(day.getMonth().getYear().getValue() != 1900) {
day.getMonth().getYear().yearReducton();
if(day.getMonth().getYear().isLeapYear())
t = t + 366;
else
t = t + 365;
}
if(day.getMonth().getYear().getValue() == 1900)
break;
}//把年份统一
if(date.day.getValue() != 1) {
t1 = t1 + date.day.getValue() - 1;
date.day.resetMin();
}//把天归一
while(true){
if(date.day.getMonth().getValue() != 1) {
date.day.getMonth().monthReduction();
date.day.resetMax();
t1 = t1 + date.day.getValue();
}
if(date.day.getMonth().getValue() == 1)
break;
}//把月归一
while(true) {
if(date.day.getMonth().getYear().getValue() != 1900) {
date.day.getMonth().getYear().yearReducton();
if(date.day.getMonth().getYear().isLeapYear())
t1 = t1+366;
else
t1 = t1+365;
}
if(date.day.getMonth().getYear().getValue() == 1900)
break;
}//把年份统一
return Math.abs(t-t1);//计算两天的差值
}//求两天只差
}
class Year{
private int value;
public Year() {
}//无参构造
public Year(int value) {
this.value = value;
}//含参构造
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
//set,get创建方法
public boolean isLeapYear()
{
if(value % 4 == 0 && value % 100 != 0)
return true;
if(value % 400 == 0)
return true;
return false;
}
//判断是否为闰年
public boolean validate() {
if(value <= 2050 && value >= 1900) {
return true;
}else {
return false;
}
}//校验数据合法性
public void yearIncrement() {
this.value = value + 1;
}//年份加一
public void yearReducton() {
this.value = value - 1;
}//年份减一
}
class Month {
private Year year;
private int value;
public Month() {
year = new Year();
}//无参构造
public Month(int yearValue, int monthValue) {
year = new Year(yearValue);
this.value = monthValue;
}//含参构造
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
//set,get创建方法
public Year getYear() {
return this.year;
}
public void setYear(Year year) {
this.year = year;
}
//set,get创建方法
public void resetMin() {
this.value = 1;
}//月份最小
public void resetMax() {
this.value = 12;
}//月份最大
public boolean validate() {
if(value <= 12 && value >= 1) {
return true;
}else {
return false;
}
}//校验数据合法性
public void monthIncrement() {
this.value = value + 1;
}//月份加一
public void monthReduction() {
this.value = value - 1;
}//月份减一
}
class Day{
private int value;
private Month month;
private int[] mon_maxnum = {31,28,31,30,31,30,31,31,30,31,30,31};
public Day() {
month = new Month();
}//无参构造
public Day(int yearValue, int monthValue, int dayValue) {
month = new Month(yearValue,monthValue);
this.value = dayValue;
}//含参构造
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
//set,get创建方法
public Month getMonth() {
return this.month;
}
public void setMonth(Month month) {
this.month = month;
}
//set,get创建方法
public void resetMin() {
this.value = 1;
}//天数最小
public void resetMax() {
if(month.getYear().isLeapYear()) {
mon_maxnum[1] = 29;
}else {
mon_maxnum[1] = 28;
}
//根据闰年改变最大的天数
this.value = mon_maxnum[month.getValue()-1];
}//天数最大
public boolean validate() {
if(month.getYear().isLeapYear()) {
mon_maxnum[1] = 29;
}else {
mon_maxnum[1] = 28;
}
//根据闰年改变最大的天数
if(value <= mon_maxnum[month.getValue()-1] && value >= 1) {
return true;
}else {
return false;
}
}//校验数据合法性
public void dayIncrement() {
this.value = value + 1;
}//天数加一
public void dayReduction() {
this.value = value - 1;
}//天数减一
}


点击查看代码
class DateUtil{
private Day day;
private Year year;
private Month month;
private int[] mon_maxnum = {31,28,31,30,31,30,31,31,30,31,30,31};
//根据类图建立四个私有属性
public DateUtil() {
day = new Day();
month = new Month();
year = new Year();
}//无参构造
public DateUtil(int y, int m ,int d) {
day = new Day(d);
month = new Month(m);
year = new Year(y);
}//含参构造
public Year getYear() {
return this.year;
}
public void setYear(Year year) {
this.year = year;
}
//set,get创建方法
public Month getMonth() {
return this.month;
}
public void setMonth(Month month) {
this.month = month;
}
//set,get创建方法
public Day getDay() {
return this.day;
}
public void setDay(Day day) {
this.day = day;
}
//set,get创建方法
public void setDayMin() {
day.setValue(1);
}//设置日期最小值
public void setDayMax() {
if(year.isLeapYear()) {
mon_maxnum[1] = 29;
}else {
mon_maxnum[1] = 28;
}
day.setValue(mon_maxnum[month.getValue() - 1]);
}//设置日期最大值
public boolean checkInputValidity() {
if(month.validate() && year.validate() && day.getValue() >= 1&&day.getValue() <= mon_maxnum[month.getValue() - 1]) {
return true;
}else {
return false;
}
}//检验数据合法性
public boolean compareDates(DateUtil date){
if(date.getYear().getValue() > year.getValue()) {
return false;
}else if(date.getMonth().getValue() > month.getValue() ){
return false;
}else if(date.getDay().getValue() > day.getValue()) {
return false;
}else
return true;
}//比较两个日期的大小
public boolean equalTwoDates(DateUtil date){
if(this.day.getValue() != date.getDay().getValue())
return false;
else if(this.month.getValue() != date.getMonth().getValue())
return false;
else if(this.year.getValue() != date.getYear().getValue())
return false;
else
return true;
}//判断两个日期是否相等
public String showDate(){
return this.year.getValue() + "-" + this.month.getValue() + "-" + this.day.getValue();
}//日期格式化
public DateUtil getNextNDays(int n){
int i = n;
for(;i > 0;i--)
{
if(year.isLeapYear()) {
mon_maxnum[1] = 29;
}else {
mon_maxnum[1] = 28;
}//根据闰年判断二月的天数
if(day.getValue() == mon_maxnum[month.getValue() - 1]) {
//根据特殊情况选择分支
if(month.getValue() == 12) {
month.resetMin();
setDayMin();
year.yearIncrement();
}
else {
month.monthIncrement();
setDayMin();
}
}
else {
day.dayIncrement();
}//一天一天求下一天
}
return this;
}//求下n天
public DateUtil getPreviousNDays(int n) {
int i = n;
for(; i > 0; i--)
{
if(day.getValue() == 1) {
//根据情况选择不同语句进行操作
if(month.getValue() == 1) {
year.yearReducton();
month.resetMax();
setDayMax();
}
else {
month.monthReduction();
setDayMax();
}
}
else
day.dayReduction();
}//通过求n个前一天来求前n天
return this;
}//求前n天
public int getDaysofDates(DateUtil date) {
int t = 0,t1 = 0;//给定两个整形记录相差的天数
if(day.getValue() != 1) {
t = t + day.getValue() - 1;
setDayMin();
}//把天数归一
while(true){
if(month.getValue() != 1) {
month.monthReduction();//月减一
setDayMax();//读取最大天数赋给t
t = t + day.getValue();
}
if(month.getValue() == 1)
break;
}//把月归一
while(true) {
if(year.getValue() != 1820) {
year.yearReducton();
if(year.isLeapYear())
t = t + 366;
else
t = t + 365;
}
if(year.getValue() == 1820)
break;
}//把年份统一
if(date.getDay().getValue() != 1) {
t1 = t1 + date.getDay().getValue() - 1;
date.setDayMin();
}//把天归一
while(true){
if(date.getMonth().getValue() != 1) {
date.getMonth().monthReduction();//月减一
date.setDayMax();//读取最大天数赋给t1
t1 = t1 + date.getDay().getValue();
}
if(date.getMonth().getValue() == 1)
break;
}//把月归一
while(true) {
if(date.getYear().getValue() != 1820) {
date.getYear().yearReducton();//年减一
if(date.getYear().isLeapYear())//判断闰年
t1 = t1 + 366;
else
t1 = t1 + 365;
}
if(date.getYear().getValue() == 1820)
break;
}//把年份统一
return Math.abs(t-t1);//返回差值
}//求两天只差
}
class Year{
private int value;
public Year() {
}//无参构造
public Year(int value) {
this.value = value;
}//含参构造
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
//set,get创建方法
public boolean isLeapYear()
{
if(value % 4 == 0 && value % 100 != 0)
return true;
if(value % 400 == 0)
return true;
return false;
}
//判断是否为闰年
public boolean validate() {
if(value <= 2020 && value >= 1820) {
return true;
}else {
return false;
}
}//校验数据合法性
public void yearIncrement() {
this.value = value + 1;
}//年份加一
public void yearReducton() {
this.value = value - 1;
}//年份减一
}
class Month {
private int value;
public Month() {
}//无参构造
public Month(int value) {
this.value = value;
}//含参构造
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
//set,get创建方法
public void resetMin() {
this.value = 1;
}//月份复位最小
public void resetMax() {
this.value = 12;
}//月份复位最大
public boolean validate() {
if(value <= 12 && value >= 1) {
return true;
}else {
return false;
}
}//校验数据合法性
public void monthIncrement() {
this.value = value + 1;
}//月份加一
public void monthReduction() {
this.value = value - 1;
}//月份减一
}
class Day{
private int value;
public Day() {
}//无参构造
public Day(int value) {
this.value = value;
}//含参构造
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
//set,get创建方法
public void dayIncrement() {
this.value = value + 1;
}//天数加一
public void dayReduction() {
this.value = value - 1;
}//天数减一
}
这分别为两个日期问题的类图,从类图中不难看出他们解决的问题是相同的,但是这两个类的逻辑关系有着明显的区别,第五题的聚合关系为一级一级调用,我认为这个看起来合理,实际上存在很多问题,这些类从图中可以看出他们存在的话必须年、月、日一起共存在一起,从实际生活出发感觉还是有不合理的地方,正常我们年、月、日都能单独存在。像第二个类图中表现的关系,day,month,year三个类都可以从DateUtil类中分别调用,彼此之间没有必要的关系,关系全由DateUtil来连接,这样的设计感觉更加的合理。它们两个代码的最大复杂度都超过最大值了,但其他值基本都是正度值,这个代码就相对合理,虽然还是有很大的复杂性,但随着之后更多的设计,应该能够让代码的各种值都维持在一个正常的水平。
菜单四是菜单三的迭代,菜单三的难度相对菜单四比较简单,但是由于当时时间原因,并没有成功的完全菜单三,导致菜单四的编码难度直线提高。
下面是菜单四的类图





从几个生成的类图可以看出,在主方法中,代码的各类复杂度都明显的超标了,所以我认识到我设计的菜单系统的基本代码是有问题的。现在总结发现,写题目的时候我是根据题目需求来慢慢增加代码量的,导致后面发现问题的时候根本不好改动代码了,我自己设计的本身就不是很合理。所有现在我意识到应该先去有一个整体的框架结构,让所有的类都能执行他们各自拥有的功能。有些属性应该放进特定的类中,这些应该先在写代码前构思好。我是想起一个加一个,导致pta的得分点到后面修改一个可能会变成一个对了另一个错了的情况,证明了拥有一个好的框架以及清晰的思路才是最重要的。

第六次作业作业是第四次第一题菜单的迭代。但由于菜单三没做出来,导致了这一次做菜单四比较困难。这道题的题目给的基本类必须要用,同时在菜单三的基础上需要增加17个报错点,而且需要大概1700行代码。所以,感觉必须要先完成基础的菜单三,才能比较好地完成菜单四。
3.踩坑心得
在第五次作业的第五题中有以下错误

如果正确输出的话应该是以下结果

从eclipse的提示看出,我的类中为空,证明我的构造方法有问题,正常应该新建立一个对象来储存数据,不然数据无法正确保留

将类中的构造方法啊正确改变时,输出的结果就变为正确了
另外感觉该题的聚合逻辑有点错误,需要一级一级实现代码的生成,特别感觉是这个数组

这个数组它是私有属性,可是它需要在DateUtil类中调用,导致了这个数组不能直接访问,然后Day类中也没有数组的setter和getter方法,不能比较便捷地更改和调用数组中的数据


以求下n天的函数为例,正常的话需要调用数组中的值,来对比day值和当前月的最大天数是否相等,可因为私有属性的原因我不能直接的去使用它,所以我也认为这个类图的逻辑存在着些许问题。然后我转换思维,运用了其他的构造方法来间接的调用数组中存放的数据。先用一个int类型的数据来存储当前是几号,然后再用day.resetMax()函数覆盖原本day中value的值,将两个数据比较完成之后,再用setter方法把原本的day值赋回value中。原本感觉直接可以使用的方法变成了间接使用,就感觉这个类图明显存在缺陷。
第6题和第五题相似,但感觉聚合关系更加合理,出的问题也相对更少

这个错误的结果主要与setDayMax()有关,回答最大值正常是没有错误的,但是二月中天数会随着闰年的到来而发生改变,但是数组的值并没有及时做出相应改变,导致结果会发生错误。所有做出以下修改

此时程序可以正确运行并且不报错
在第四次作业的第四题中也出现了问题


这个程序能做到最基础的排序以及文本的输出,但是并不能去重,因此根据题目要求TreeSet才是最佳的选项,set集合可以自动做到去重并且运行速度极快,而TreeSet可以在set集合的基础上进行排序,更加切合题意,能实现代码的优化。
这两段代码是菜单四中我出现的典型错误
点击查看代码
void delARecordByOrderNum(int orderNum){
for(int i = 0;i < t;i ++) {
if(records[i].orderNum == orderNum)
records[i] = null;
else
System.out.println("delete error;");
}
//根据序号删除一条记录
}
点击查看代码
public void delARecordByOrderNum(int orderNum){
int in = -1;
for(int i = 0;i < t;i ++) {
if(records[i].orderNum == orderNum) {
in = i;
break;
}
}
if(in != -1) {
records[in].num = 0;
records[in].trueSum = 0;
}else
System.out.println("delete error;");
//根据序号删除一条记录
}
4.改进建议
菜单四我目前想去重构思维,重读一遍题目,把所有需要的属性都进行归类放在不同的类中,然后在类中依据题目的需求编辑各种方法,通过一次次的尝试,慢慢将代码完善,将功能进行完善。之后再开始进行主函数的编码,将基础的类生成,需要输入以及判断的各种类型用if语句进行判断。之后再通过类中的方法或者属性的更改,将总体的功能实现。现在个人认为框架比盲目写好,这次盲目写发现代码量一大容易写到头,改到一定程度的时候就改不下去了,基本很难再实现别的功能了,而且功能可能会有冲突,所以先构思出一个类似地基功能的基础代码是非常重要的。
5.总结
通过这三次作业,我了解了正则表达式在判断数据类型时比用if语句来的更为便捷,对于类的调用以及定义更加熟练了,了解了非空返回异常可能出现的原因。对面代码的整体框架需要有一个严谨的思维逻辑,在编码时考虑部分代码在整体中是否会有冲突这方面还需要加强。作业方面我希望还是慢慢迭代上来比较好写,没有写过菜单一和二,直接写三和四,感觉写的时候方向都很迷惑,而且感觉pta作业可能直接从500行代码飞跃到1700行。希望还是慢慢加上去,而不是代码量突然爆炸。

浙公网安备 33010602011771号