OOP第二次博客作业

1.前言

总结第4-6次题目集的知识点、题量、难度等情况

深入接触Java
相对于前面三次作业,这时候我感觉逐渐认识到了Java设计或者说时面向对象设计的设计思维。相对于面向过程编程而言面向对象更加注重对对象的拆分,分析不同类、对象之间的关系,随后设计相应的方法。对于面向对象编程更像是将面向过程的编程用对象的形式拆解开,对我而言在编写的大作业时减轻了我的设计压力,因为将对象拆解的过程也就是编程的步骤化,如果是面向过程编程就需要将所有的步骤一下想出来,并且一口气编写出来,否则过一段时间回来编写,函数之间的弱逻辑很容易忘记之前编写代码的思路而导致不必要的时间花费。

涉及知识点
类与类之间的关系,HashMap<>,List,ArrayList类,多态,父类与子类,接口,子类的赋用。

难度吐槽(bushi)
nchu-software-oop-2024-上-4:(万恶的答题程序的终结),在最后的迭代里卖反而没有了新的设计,只是增加了需要判断的题的类型,(根据非专业侦探的非严密推理),或许是在为后面电路问题的复杂的父类子类关系做铺垫,这道题的主要难点应该是多选题和填空题的if判断,容易漏掉一些情况。
nchu-software-oop-2024-上-5:第一次遇到如此抽象的题(电路电流流动的物理模型需要抽象为数学模型),找不到对象。对象分类不仅仅局限于可见的设备,还有电路控制台,电路本身,总之在整个电路中对象的概念比较模糊,难以建类。
nchu-software-oop-2024-上-6:在第五次大作业的电路设计的基础上第六次设计途中思路就比较清晰了,由于串接设备,电压分配都属于两个主要的行为,电路设计过程中有很多地方用到了多态和子类的复用来处理,设计重写共同行为的方法。这些都是其次,最让我头痛共同行为下串联和并联电路的开关和电阻截然不同的处理(赞美多态aaaaa!!!!!!)。

2.设计与分析

对题目的提交源码进行分析

nchu-software-oop-2024-上-4

UML图

代码分析图

小结:
这道题最主要的是题目类的拓展,拓展了两种题型:1、填空题,2、多选题。这两个题目判断都涉及到了全对,全错和不完全对这三种判分情况,对应着对考生答案List与标准答案List的分支判断。其中多选题相比较与填空题的判断要稍微简单一点,主要思路是先判断考生答案和标准答案的数量(长度)相等、大于、小于,由此再做出完全没有歧义的分支,将所有情况覆盖到,以下有多选题的判断部分代码,填空题在相同思路上多出寻找字串的这一步骤。
:在StringList中寻找字串用到indexOf()方法,(if(tempPaper.K_subjectList[i_s[i]].StandStr().indexOf(answer.answerList[i+1])==-1)//未找到),寻找字串真的好用。

多选题判题

 if(juge[tempPaper.scoreNumber[i]]==1)//循环不要用i
    	{
    		int flag=0;//标记找到的题目的数量
    		if(!tempPaper.Z_subjectList[i_s[i]].getExist())//被删除
        	{
        		//System.out.println(String.format("the question %d invalid~0",i_s[i]+1));
        		System.out.println(String.format("the question %d invalid~0",tempPaper.Z_subjectList[i_s[i]].getNum()));
        		score[i]=0;
        	}
    		else//开始判题
    		//包含一个错误答案或完全没有答案给0分;包含部分正确答案且不含错误答案给一半分,如果一半分值为小数,按截尾规则只保留整数部分
    		{
    			String part[]=answer.answerList[i+1].split(" ");
    			if(part.length>tempPaper.Z_subjectList[i_s[i]].getStandListLen())//多出来绝对有错误答案
    			{
    				score[i]=0;//录入成绩
    				System.out.println(tempPaper.Z_subjectList[i_s[i]].Content()+"~"+answer.answerList[i+1]+"~"+"false");
    			}
    			else//答案就是小于等于了
    			{
    				if(part.length==tempPaper.Z_subjectList[i_s[i]].getStandListLen())//等于,要么有错要么全对
    				{
    					for(int j=0;j<tempPaper.Z_subjectList[i_s[i]].getStandListLen();j++)
            			{
            				for(int k=0;k<part.length;k++)
            				{
            					if(tempPaper.Z_subjectList[i_s[i]].getStandList()[j].equals(part[k]))
            						flag++;//找到增加对的题目
            				}
            			}
    					if(flag<tempPaper.Z_subjectList[i_s[i]].getStandListLen())//小于就证明其中有错误的
    					{
    						score[i]=0;
    						System.out.println(tempPaper.Z_subjectList[i_s[i]].Content()+"~"+answer.answerList[i+1]+"~"+"false");
    					}
    					else
    					{
    						score[i]=Integer.parseInt(tempPaper.scorelist[tempPaper.scoreNumber[i]]);
    						System.out.println(tempPaper.Z_subjectList[i_s[i]].Content()+"~"+answer.answerList[i+1]+"~"+"true");
    					}
    				}
    				else//答案小于
    				{
    					for(int j=0;j<tempPaper.Z_subjectList[i_s[i]].getStandListLen();j++)
    					{
    						for(int k=0;k<part.length;k++)
    						{
    							if(tempPaper.Z_subjectList[i_s[i]].getStandList()[j].equals(part[k]))
            						flag++;
    						}
    					}
    					if(flag!=part.length)
    					{
    						score[i]=0;
    						System.out.println(tempPaper.Z_subjectList[i_s[i]].Content()+"~"+answer.answerList[i+1]+"~"+"false");
    					}
    					else//答案全,得半分
    					{
    						score[i]=Integer.parseInt(tempPaper.scorelist[tempPaper.scoreNumber[i]])/2;
    						System.out.println(tempPaper.Z_subjectList[i_s[i]].Content()+"~"+answer.answerList[i+1]+"~"+"partially correct");
    					}
    				}
    					
    			}
    			
    			
    		}
    	}

本题踩坑:
1.如上图代码所示,没有用HashMap<>这一类,只是将题号作为键创建数组实现题目的映射操作,导致最后迭代对题目要求越来越多了之后就会出现数组下标中又套下标的情况,不仅在写代码的时候费劲,在修改代码错误的时候也是要绕很多弯。(贴个代码感受一下)
if(tempPaper.Z_subjectList[i_s[i]].getStandList()[j].equals(part[k]))
2.在进行多选题和填空题的错误判断时会漏掉一些情况,诚然用“if ;else if”的结构能够将自己的完全分类的情况准确列举出来,但这也恰好是缺点所在,在多数情况下确实能正确判断,但是在复杂或者隐性条件下就会漏掉一些情况而不知,可以优先将题目判断分为两个将绝对正确的条件用if写出来剩下用else,然后再用if,else嵌套完成判断。

nchu-software-oop-2024-上-5

UML图

代码分析图

小结:
这道题是继答题程序之后的新的电路系统,又要重新寻找对象和类之间的关系,并且将电路数学建模。在建立关系的过程的我发现风扇等电器都有很多相似的行为和属性,所以抽象建立一个“设备”父类,但是后续迭代复杂起来了显然电路缺少了什么,缺少了不同的串联电路和并联电路,再分析串并联电路之间“套娃”的连接这里大胆也将串并联电路也视为电器设备同样将“设备”视为父类,再来思考串并联电路确实许多和电器相似行为(将串并联电路中复杂的电路设备视为一个大的自己重新设置的电器),设计目前看来合理。最后是所有对象的之间的交互,还是少不了类似上一道答题程序题中答题类的存在,就设计了一个控制台类,处理电路设备之间的交互。

本题踩坑:
1。设计相同了还是挺好写的,就是后面交上去后就是有一些样例过不了,分析之后发现是设备运转逻辑出现了问题,没有对极限情况(非正常输入)进行判断,这里出现的就有分档调节器中的边界问题,在减过头和加过头都要进行限制

限制处理

	public void ChangDang(char a)
	{
		if(a=='-'&&D_len>=1)
			D_len--;
		if(a=='+'&&D_len<=2)
			D_len++;
	}

感觉在自己检查出分档器的问题之后感觉对程序设计的完备性有了进一步的理解(涉及数值变换的地方就要考虑数据的边界运行)。

nchu-software-oop-2024-上-6

UML图

代码分析图

小结:
套娃,是套娃,我加了套娃。当然要实现这种套娃效果就需要在运行电路时有一个相同的行为,明显电路运行是对着一条广义的串联电路的,换言之就是要将串并联又给其涉及一个电路类的父类,当然前面的“设备”父类的性质任然具有,所以“设备”类光荣晋升为爷类(超级加辈)。
在这个题目的多态的使用中确实会有对一些子类不同与其他类的处理,这时候就需要intensOf()来识别多态中的实际对象进行特殊处理:
特殊处理:

public void chang()
	{
		double realV=0;//目前的串联电路没有零值
		double startV=0;//当头电压,没有分配之前的电压//电压不再是流动,而是直接设置
		if(this.group.getIsV()==0)
		{	if(this.deviceList[0] instanceof Engin)
				startV=this.deviceList[0].PutPin2_v();			
		}
		else
			startV=0;
		//System.out.println("you get start "+startV);
		for(int i=0;i<Dlen-1;i++)//传电压,在修改命令之后
		{
			if(this.deviceList[i] instanceof Ldang||this.deviceList[i] instanceof Fdang)
			{
				deviceList[i].SetPin1_v(startV);
				startV=deviceList[i].PutPin2_v();
				//System.out.println("changd V is "+startV);
			}
			
			realV=(this.deviceList[i+1].getresistance()/this.group.getresistance())*startV;//自己分配到的电压
			//System.out.println(realV+"you gt bili "+this.deviceList[i+1].getResistanceB());
			deviceList[i+1].SetPin1_v(realV);
			
		}
		//System.out.println("end chang()");
	}

很好用,真的很好用,在复杂工具类(main,控制台类)中设计自己内部使用的方法,在Main中就是设计专属静态方法,也是将冗长代码拆开编写,要轻松许多。

本题踩坑:
1.对我本人而言这次迭代最大最坑的坑的当属并联中的串联电路开关的变化导致的并联电阻的变化,我竟然痴心妄想在控制台中进行遍历改变时判断并联中的串联的开关状态再动态改变整个电路的总电阻和不同的电气设备的电阻,那是稍微想一下都是不可能的(我的方法计算的时候就需要知道总电压和分电压,而遍历到并联中的串联中的开关的时候肯定就有设备计算过了),所以应该在进入控制台之前就判断好电阻状态,所以我就在进行电路计算之前就将串并联电路的电阻修改情况设置好了,稍微小结一下,我就应该判别好动态变化的成员,安排好变化的位置。
2.到这道题,我对子类赋用给父类的多态使用上出现了很大的问题的。我先将每个电器的电阻在子类里面又单独设置了,但是进行调用电阻计算的方法又在父类中没有在子类中重写,这导致在实际使用时实际类型使用的方法调用的使用父类的未单独设置的电阻(this.进行调用),然后代码就出现了一大堆错误,修改了半天。

3.编码改进

对相应题目的编码改进给出自己的见解,做到可持续改进

编码思路:与面向过程的程序设计不同,面向对象的程序设计不仅要考虑解题的大体步骤更要设计好在解题过程中的对象与对象之间的关系以及相互作用,前期因为我没有怎么思考对象之间的关系导致写着写着就要卡住,特别时遇到了电路这种物理模型的抽象化,不仅仅是聚焦在可见的可见的对象上,为了运行也要增加类似与电路类这种没有直接出现的对象。
做题初步思考:刚刚开始看题目确实有点头晕不知道要怎么实现,但是首先像现实中的模型一样去思考,再在是否可以代码化的基础上再去一步步来修改,比如电流的流动就是代码中电压的赋予。

4.总结

对本阶段三次题目集的综合性总结,学到了什么,哪些地方需要进一步学习及研究,对教师、课程、作业、实验、课上及课下组织方式等方面的改进建议及意见

感受:经过这几次的题目集的折磨后自我感觉对Java的编程也是越来越得心应手了,既能分为对象写出相应的方法,也能最后将所有的对象的方法交互使用。虽然在具体使用的时候对象方法的设计会有所出入,但是大体思路不变的情况下还是挺容易修改的,所以呢就要大胆地依托对象进行方法的设计,后面再进行精修。
交流:虽然老师叫我们不能抄袭代码,但是合适的交流能很好转换陷入僵局的思路,比如前文提到我刚刚开始对串并联电阻的愚蠢的处理就是靠着和同学交流了一下她设计的思路回去修改出来(当然关于电阻那一大份是大改,嘤嘤嘤)。

5.后言

果然啊,熟练程度和编码感觉都是靠代码行数给堆砌上去的,多打代码多总结确实有用,但是刚刚起头的那一段时间是真的掉头发啊!!!!!!

posted @ 2024-06-02 14:37  罗颖  阅读(13)  评论(0编辑  收藏  举报