Object-Oriented-Design-and-Analysis

编程思想:面向对象Java总结

NO0、前言

第一次发表博客,总结这一个半月以来三次作业情况及对编程思想跨越的理解和收获,对比总结面向对象和面向过程的差异,C语言和Java的异同。

NO1、作业过程总结

1、三次作业是循序渐进的,后一次的作业都是建立在前一次的基础上:

第一次作业许多地方都和C语言思想相似,可以说是最简单的c操作,表达形式上除了一些细节上的不同比如输入输出语句,并没有用到其他的和面向对象有关的思想,所有的代码都写在main函数中,无调用关系和操作,这一次作业都是面向过程的,除了几个测试点比较难改外(问了班上的大佬),这次作业难度并不大,第一天把代码都提交了第二天把几个没过的点也改对了,自我感觉良好;

第二次作业涉及到Java中独有的名词"方法",即在Main这个大类创建若干个方法供主函数调用,这一波操作使主函数更加简洁明了,但是主要思想和C语言中把可复用的代码块写成一个个函数没什么区别,在进一步加强面向对象的思想中也提高了编程的难度,这次作业一开始进度较慢,在如何向主函数里new一个对象用来调用方法上花了点时间,第一天只写对了前三道题,最后一题第二天中午提交了;

然而第三次作业就没有这么顺利了,虽然第三次作业的内容继承了第二次的一元二次方程和求日期,编程思路都大同小异,但是它和上一次又有所不同,第二次的编程只有一个Main类,其中包含所有的方法,而第三次不仅包含一个Main类存放主函数还有其他的包含多个方法的类,实现了多个类之间对象方法的调用,而且对象把自己的数据(属性)隐藏起来,外部无论是访问还是赋值,都必须按照各自的类自己定义规范;第三次作业中还涉及到聚合类的关系,它是关联关系的一种,是强的关联关系。聚合是整体和个体之间的关系。例如在第三次第三题”求日期“中DateUtil与Year、Month、Day类之间的关系便整体和个体的关系。与关联关系一样,聚合关系也是通过实例变量实现的。但是关联关系所涉及的两个类是处在同一层次上的,而在聚合关系中,两个类是处在不平等层次上的,一个代表整体,另一个代表部分。 

2、作业过程中遇到的问题及解决方法:

首先再第一次作业中并没有碰到什么设计代码思路上的大困难,到是再一些小细节上有些纠结,像一开始不知道Java编译是默认double类型的数据类型,在写“计算税率”时定义了double类型的变量,输出时还一直在想保留小数点后两位float和double是怎么转换的,最后观看了中国大学慕课上的视频才理解了:

 

 

 

 

 

 

 

 

 

 

 

 

 

还有第四题“判断三角形类型”的一个测试点判断直角三角形用了常规思维:if(Math.pow(a,2)==Math.pow(b,2)+Math.pow(c,2))其实这样表示理论上是可以的,但是在测试点的检查下考虑判断直角有精度问题,即斜边是无理数:

 

 还有最后一题"统计最大数出现次数“中判断最大数用了do....while循环,因为do....while一定要输入一个后才判断,导致输入单独的0时没有输出:

我把它最后改成了while循环就欧克了:

 

第二次作业中第一题的数组传值问题,一开始new了一个eqn[]数组时没有给他传值进去,导致输出有问题: 

后面发现问题追加了给数组赋值的语句:

由于受了前面等腰直角斜边无理数的影响导致我在判断根的判别式时也用了无理数:

印象最深的还是第三次日期类设计问题,其中最开始没搞明白DateUtil getNextNDays(int n)方法要返回什么样类型的参数,传了一个null,导致最后输出有问题:

最后反应过来应该new一个DateUtil类型的对象date用它返回所求的日期:

在第二次作业中"求前n天的日期"直接按照惯性思路用for循环一天一天往前推,遇到特殊日期就分类if else处理:

//前n天的for循环: 
for(int i=1;i<=d;i++) { 
         day--; 
         if((month==2||month==4||month==6||month==8||month==9||month==11)&&(day==0)) { 
         month--; 
         day=31; 
         } 
         else if((month==5||month==7||month==10||month==12)&&(day==0)) { 
         month--; 
         day=30; 
         } 
         else if((month==3)&&(day==0)){ 
             month--; 
         if((year%4==0)&&(year%100!=0)||(year%400==0)) 
             day=29; 
         else
             day=28; 
         } 
             else if((month==1)&&(day==0)) { 
             year--; 
             month=12; 
             day=31; 
             } 
            } 

 

 

 

 

然而第三次却行不通,为了解决测试点的超时问题你得一个月一个月地往前减,最后才按天数地减,特殊时期特殊处理。

//While循环求前n天日期: 
int s=0; 
int[][] mo= {{31,31,28,31,30,31,30,31,31,30,31,30,31},{31,31,29,31,30,31,30,31,31,30,31,30,31}}; 
        if(isLeapYear(year)) 
            s=1; 
        else
            s=0; 
        while(n-mo[s][month-1]>=0) { 
            n=n-mo[s][month-1]; 
            month--; 
            if(month==0) { 
                year--; 
                month=12; 
                if(isLeapYear(year)) 
                    s=1; 
                else
                    s=0; 
            } 
        } 
        day=day-n; 
        if(day<0) 
        { 
            day=mo[s][month-1]+day; 
            month--; 
            if(month==0) { 
                year--; 
                month=12; 
            } 
        } 

 

 

 

 

 最后在解二元一次方程的地方要注意重复定义变量的问题,由于D被定义了两次导致判别式大于0时最后输出两个根一样:

NO2、设计心得:从面向过程过渡到面向对象

面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了,例如第一次作业中的"判断坐标点的所在范围"new出一个对象坐标点(x,y)的值,在主函数中直接用它就可以了,并不涉及到调用与被调用的复杂关系。

面向对象就是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为,比如第三次作业中解一元二次方程,创建一个QuadraticEquation类的对象equation,然后这个equation对象在主函数中调用自己getRoot1,getDiscriminant方法,在QuadraticEquation类中定义了自己的私有属性和方法,即你可以在QuadraticEquation中,规范属性啊a,b,c,D,r1,r2的范围,体现了面向对象的特征:封装性

mian函数中new对象:

QuadraticEquation equation = new QuadraticEquation(a,b,c); //create a QuadraticEquation object
double discriminant = equation.getDiscriminant();//get value of b * b - 4 * a * c

 

 

 

 

用面向对象思路解决二元一次方程问题

class QuadraticEquation { 
    private double a; 
    private double b; 
    private double c,D; 
    private double r1,r2; 
    public QuadraticEquation(double a, double b, double c) { 
        this.a=a;this.b=b;this.c=c; 
        } 
    public double getDiscriminant() { 
D=(Math.pow(b,2))-4*a*c; 
        return D; 
    } 
    public double getA() { 
        return a; 
    } 
    public double getB() { 
        return b; 
    } 
    public double getC() { 
        return c; 
    } 
    public double getRoot1() { 
        r1= (-b+Math.sqrt(D))/a/2; 
        return r1; 
    } 
    public Object getRoot2() { 
        r2= (-b-Math.sqrt(D))/a/2; 
        return r2; 
    } 
} 

 

 

 

 

NO3、测试的理解与实践

要测试一段代码的好坏功能优良与否,就要用到Junit,首先在你写好的代码中导入Junit包,测试类通常单独写在一个类文件里面。你可以再创建一个T_sum.java,在这个类里面你要测试刚才的方法,你需要再写一个方法:
在test.java中:

public class T_sum{
@Test 
Public void testSum(){ 
Int r=sum.sum(-1,1);//自己写的测试数据 
Assert,assrtEquals(r,0);//将设定的数据与预期结果相比较 
} 

 

 

 

下面是简单的加减乘除的测试类用例:

一般测试点都是设边界,特殊值之类的,比如在求日期时,闰年和平年,闰平2月,12月和1月,最大整型int的范围都要考虑到。

NO4、写在后面

经过前期三次的作业训练,对面向对象的编程思路有了一个大概的了解,知道了如何画UML图使得类与类之间、属性与方法之间的关系简单明了,在以后的学习面向对象编程中,希望自己尽量往创建一个对象,用这个对象执行方法来解决问题的方面考虑,而不是一拿到题就用面向过程的思维去解决问题;还有自己写的代码总是出现各种各样的bug而过不了测试点,导致编程速度欠缺,希望以后提高改bug的速度。

 

分类:

技术点:

相关文章: