oop作业4到6次总结

1.前言

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

2.设计与分析

第五次作业的第五题和第六题功能相似,但是结构明显不同,感觉出了C语言和Java明显的区别,对象和对象之间可以有不同的关系,怎么合理的设计对象与对象之间的关系感觉是学好Java的必修课。
image
image

点击查看代码
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;
    }//天数减一
    
}




image
image

点击查看代码
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来连接,这样的设计感觉更加的合理。它们两个代码的最大复杂度都超过最大值了,但其他值基本都是正度值,这个代码就相对合理,虽然还是有很大的复杂性,但随着之后更多的设计,应该能够让代码的各种值都维持在一个正常的水平。
菜单四是菜单三的迭代,菜单三的难度相对菜单四比较简单,但是由于当时时间原因,并没有成功的完全菜单三,导致菜单四的编码难度直线提高。
下面是菜单四的类图
image
image
image
image
image
从几个生成的类图可以看出,在主方法中,代码的各类复杂度都明显的超标了,所以我认识到我设计的菜单系统的基本代码是有问题的。现在总结发现,写题目的时候我是根据题目需求来慢慢增加代码量的,导致后面发现问题的时候根本不好改动代码了,我自己设计的本身就不是很合理。所有现在我意识到应该先去有一个整体的框架结构,让所有的类都能执行他们各自拥有的功能。有些属性应该放进特定的类中,这些应该先在写代码前构思好。我是想起一个加一个,导致pta的得分点到后面修改一个可能会变成一个对了另一个错了的情况,证明了拥有一个好的框架以及清晰的思路才是最重要的。
image
第六次作业作业是第四次第一题菜单的迭代。但由于菜单三没做出来,导致了这一次做菜单四比较困难。这道题的题目给的基本类必须要用,同时在菜单三的基础上需要增加17个报错点,而且需要大概1700行代码。所以,感觉必须要先完成基础的菜单三,才能比较好地完成菜单四。

3.踩坑心得

在第五次作业的第五题中有以下错误
image
如果正确输出的话应该是以下结果
image
从eclipse的提示看出,我的类中为空,证明我的构造方法有问题,正常应该新建立一个对象来储存数据,不然数据无法正确保留
image
将类中的构造方法啊正确改变时,输出的结果就变为正确了

另外感觉该题的聚合逻辑有点错误,需要一级一级实现代码的生成,特别感觉是这个数组
image
这个数组它是私有属性,可是它需要在DateUtil类中调用,导致了这个数组不能直接访问,然后Day类中也没有数组的setter和getter方法,不能比较便捷地更改和调用数组中的数据
image
image
以求下n天的函数为例,正常的话需要调用数组中的值,来对比day值和当前月的最大天数是否相等,可因为私有属性的原因我不能直接的去使用它,所以我也认为这个类图的逻辑存在着些许问题。然后我转换思维,运用了其他的构造方法来间接的调用数组中存放的数据。先用一个int类型的数据来存储当前是几号,然后再用day.resetMax()函数覆盖原本day中value的值,将两个数据比较完成之后,再用setter方法把原本的day值赋回value中。原本感觉直接可以使用的方法变成了间接使用,就感觉这个类图明显存在缺陷。
第6题和第五题相似,但感觉聚合关系更加合理,出的问题也相对更少
image
这个错误的结果主要与setDayMax()有关,回答最大值正常是没有错误的,但是二月中天数会随着闰年的到来而发生改变,但是数组的值并没有及时做出相应改变,导致结果会发生错误。所有做出以下修改
image
此时程序可以正确运行并且不报错
在第四次作业的第四题中也出现了问题
image
image
这个程序能做到最基础的排序以及文本的输出,但是并不能去重,因此根据题目要求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;");
		
		
		//根据序号删除一条记录
	}
这两个是判断重复删除必不可少的代码,最除我将这个数组直接返回空在单个删除是没有问题的,但是重复删除时,它再次判断删除条件时,Java会监测到这个数组中为null,这样会直接报错。因为我写的函数判断条件是判断他们的订单号,并且重复删除也只要清空一次就够了。所有换一种方法,将它的订单号改为0,让判断条件不能正确识别到,但是可以正确执行重复删除的测试点了。

4.改进建议

菜单四我目前想去重构思维,重读一遍题目,把所有需要的属性都进行归类放在不同的类中,然后在类中依据题目的需求编辑各种方法,通过一次次的尝试,慢慢将代码完善,将功能进行完善。之后再开始进行主函数的编码,将基础的类生成,需要输入以及判断的各种类型用if语句进行判断。之后再通过类中的方法或者属性的更改,将总体的功能实现。现在个人认为框架比盲目写好,这次盲目写发现代码量一大容易写到头,改到一定程度的时候就改不下去了,基本很难再实现别的功能了,而且功能可能会有冲突,所以先构思出一个类似地基功能的基础代码是非常重要的。

5.总结

通过这三次作业,我了解了正则表达式在判断数据类型时比用if语句来的更为便捷,对于类的调用以及定义更加熟练了,了解了非空返回异常可能出现的原因。对面代码的整体框架需要有一个严谨的思维逻辑,在编码时考虑部分代码在整体中是否会有冲突这方面还需要加强。作业方面我希望还是慢慢迭代上来比较好写,没有写过菜单一和二,直接写三和四,感觉写的时候方向都很迷惑,而且感觉pta作业可能直接从500行代码飞跃到1700行。希望还是慢慢加上去,而不是代码量突然爆炸。

posted @ 2023-04-26 18:01  22201135-余耀  阅读(50)  评论(0)    收藏  举报