pta作业第一次总结(涵盖对面向对象的理解)

0. 前言

本次博客针对的主要是pta上的前三次Java作业,对其进行一些总结、思考等;这三次作业的难度是逐步增加的,也是逐步从面向过程编程转到面向对象编程;在这其中我会对一些概念提出自己的看法,初步总结面向对象设计的心得,但博主毕竟只是初学者,所以难免会有一些总结地不对的地方,望谅解以及指出错误。

1. 作业过程总结

①总结三次作业之间的知识迭代关系;

第一次作业的难度较低,基本上是为了让我们对java的语法、编写风格更为熟悉,了解java的一些基本概念,为后续作业打下基础;第二次作业主要是让我们在一个类中除主方法外多设计几个方法,每个方法对应着一个功能,通过在主方法中调用其他方法来实现功能,这样可以使得主方法更为简洁,为第三次作业设计类做铺垫;第三次作业则是开始进入面向对象思维来编码了,这次作业的题目是基于第二次作业来的,我们被要求去设计类来实现求解,并且能够在DateUtil类上再细分出Year、Month、Day类。总之,这三次作业难度上逐渐递增、思维上逐渐由面向过程转向面向对象。

②如何通过作业逐步从面向过程过渡到面向对象;

从面向过程过渡到面向对象既是将思维从如何具体实现一个功能转变为如何设计不同的类并调用他们来实现这个功能,可以通过作业中两个题目来说明:

这题偏向于面向过程

代码如下:

 1 import java.text.DecimalFormat;
 2 import java.util.Scanner;
 3 public class Main{
 4     static DecimalFormat fmt = new DecimalFormat("0.0000");
 5 public static void main (String[] args){
 6 Main exp = new Main();
 7 Scanner scan = new Scanner(System.in);
 8 double[] eqn = new double[3];
 9 double[] roots =new double[2];
10 for (int i = 0; i < 3; i++)
11 {
12     eqn[i] = scan.nextDouble();
13 }
14 if (eqn[0] == 0)
15 {
16     System.out.println("Wrong Format");
17     return ;
18 }
19 exp.solveQuadratic(eqn,roots);
20 
21 }
22 
23 public static int solveQuadratic(double[] eqn, double[] roots){
24 int n;
25 double judge;
26 judge = Math.pow(eqn[1], 2) - 4*eqn[0]*eqn[2];
27 if (judge < 0)
28 {
29     n = 0;
30     System.out.println("The equation has no roots");
31 }
32 else if (judge == 0)
33 {
34     n = 1;
35     roots[0] = (-1*eqn[1])/(2*eqn[0]);
36     if (roots[0] == 0)
37         roots[0] = 0;
38     System.out.println("The equation has one root: " + fmt.format(roots[0]));
39 }
40 else 
41 {
42     n = 2;
43     roots[0] = ((-1*eqn[1]) + Math.sqrt(judge))/(2*eqn[0]);
44     roots[1] = ((-1*eqn[1]) - Math.sqrt(judge))/(2*eqn[0]);
45     System.out.println("The equation has two roots: " + fmt.format(roots[0])+" and "+fmt.format(roots[1]));
46 }
47 return n;
48 }
49 }

 

这题则偏向于面向对象

代码如下:

 1 import java.util.Scanner;
 2 
 3 public class Main {
 4     public static void main(String[] args){
 5         Scanner input = new Scanner(System.in);
 6 
 7         double a = Double.parseDouble(input.next());
 8         double b = Double.parseDouble(input.next());
 9         double c = Double.parseDouble(input.next());
10         
11         if(a == 0){
12             System.out.println("Wrong Format");
13             System.exit(0);
14         }
15         
16         //create a QuadraticEquation object
17         QuadraticEquation equation = new QuadraticEquation(a, b, c);
18         //get value of b * b - 4 * a * c
19         double discriminant = equation.getDiscriminant();
20         
21         System.out.println("a=" + equation.getA() +
22                 ",b=" + equation.getB() + 
23                 ",c=" + equation.getC()+":");
24 
25         if (discriminant < 0) {
26           System.out.println("The equation has no roots.");
27         }
28         else if (discriminant == 0)
29         {
30           System.out.println("The root is " + 
31                   String.format("%.2f", equation.getRoot1()));
32         }
33         else // (discriminant >= 0)
34         {
35           System.out.println("The roots are " + 
36                   String.format("%.2f", equation.getRoot1()) 
37             + " and " +  String.format("%.2f", equation.getRoot2()));
38         }
39     }
40 }
41 
42 class QuadraticEquation {
43         //your code
44     private double a,b,c;
45     QuadraticEquation(double a,double b,double c){
46         this.a = a;
47         this.b = b;
48         this.c = c;
49     }
50     public double getA() {
51         return a;
52     }
53     public double getB() {
54         return b;
55     }
56     public double getC() {
57         return c;
58     }
59     public double getDiscriminant() {
60         double discriminant;
61         discriminant = Math.pow(b, 2) - 4*a*c;
62         return discriminant;
63     }
64     double getRoot1(){
65         return (-b + Math.sqrt(getDiscriminant()))/(2*a);
66     }
67     double getRoot2() {
68         return (-b - Math.sqrt(getDiscriminant()))/(2*a);
69     }
70     
71 }

 

 

③作业过程中遇到的问题及解决方法

(1)如图:

这可能是很多新手都会碰到的问题,错误原因:i=9,在类中是不能有直接赋值行为的。这属于逻辑操作,要放在方法中执行。 注意:在类中不在方法中的代码只能是声明,不可是具体赋值等操作

解决办法:将赋值操作放在相应的方法中执行即可

(2)类似报错:Cannot make a static reference to the non-static field a

造成这个报错的原因是静态的方法只能访问静态的成员,我们需要了解static关键字的用法:static:静态的,用于修饰成员(成员变量,成员方法);

注意事项:

1.静态的方法只能访问静态的成员;

2.非静态得方法即能访问静态得成员(成员变量,成员方法)又能访问非静态得成员;

解决办法:可将a设置为static类型变量

(3)第一次作业的7-4题目有一个测试点一直过不去

在检查代码后才发现是在判断等腰直角三角形上出了问题,我们并不能输入根号,那么在输入等腰直角三角形的斜边时我们只能输入其数值的近似值,在这过程中便会有精度的丢失,只能改进判断方法

初始判断方法:

解决方法:在上述代码的条件下改变判断方法:如果两条直角边平方和减去斜边的平方之差得到的值小于1E-6,则认为两条直角边平方和等于斜边的平方,以此来解决问题。

④每次作业花费的时间比例

第一、二次作业因题目难度较小因此花的时间较少,基本上在一个上午的样子可以完成;但是第三次作业花的时间较多,主要是自己在设计思路时有一个点忽略了导致后面找问题并修改花的时间长了些,用了2天。

⑤对编程过程的严谨性的认识及教训

编程过程中的严谨性是十分重要的,这就要求我们在编写代码时必须考虑全面,尽量将更多的情况考虑进去,这样在后续的检查中才能够减少工作量;当一个问题有多种可供选择的解决方案时,我们也需要花时间来思考哪一种方案更加合适,比较方案的优缺点,最终选择合适的方案,这也是严谨性的一方面体现;教训的话,我觉得当我们编写完一题代码后提交但是有测试点不能通过,并且也花了一定的时间还是不能找出问题时不要慌,可以先将代码放在一边,仔细的捋一遍自己的设计思路,分析这个测试点可能在哪部分代码出错的可能性,之后再去修改,基本能够找出问题所在的;总之,凡事不要慌,稳住,我们能赢!

2. OO设计心得

①面向过程与面向对象的比较

(1)首先说说对面向过程编程的理解,它是围绕着一个待解决事件为中心的编程思想,我们关注的是如何去通过分析这个待解决事件,制定相应的解决步骤,之后便是通过函数来一步步地实现我们的需求,在最后汇总使用的时候只需要调用相应的函数即可;

面向过程编程的特点可以概括为:线性化、步骤化、模块化;

因为面向过程编程不需要像面向对象编程那样调用类时需要进行实例化,消耗内存资源,开销比较大,所以面向过程编程比较适合于开发一些简单逻辑的程序,但是它也有缺点,在应对大型、复杂的程序开发中,面向过程便不能胜任了,这是因为它的维护性、扩展性、复用性比较差,在编写程序的时候如果哪个环节需要修改往往会牵一发而动全身,这样对于开发一个复杂的大型程序而言耗费的时间太长了。

常见面向过程编程语言:C

(2)但对于面向对象编程,因其易维护、易扩展、易复用、接口丰富等优点在应对复杂逻辑项目时也能游刃有余,相比于面向过程编程,面向对象编程在处理一个问题的最初时期考虑的方面一定比面向过程更多,我们必须对待解决问题进行分析,之后根据分析对类进行设计,类的设计是否合理将直接影响到后续代码的维护与复用、功能的增加与完善等。面向对象在实现相应功能时,只需要抽象出一个类,这个类中包含了与其相关的各种方法,那我们需要做的便是实例化各个对象,在不同对象下调用方法实现功能,至于类内部到底是如何实现的我们并不关心,如何实现是面向过程的事情。

常见面向对象编程语言:C++  C#  JAVA  python

②面向对象设计的基本原则理解(目前课堂上只介绍了单一职责原则)

五个基本原则:单一职责原则、开放封闭原则、依赖倒置原则、里氏替换原则、接口隔离原则

单一职责原则:类的功能要统一,不能一个类中有各种各样的功能,一个类只需要实现一个功能。

开放封闭原则:一个对象或者实体对外扩展是开放的,对内修改是封闭的。

依赖倒置原则:高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。抽象不应该依赖于具体实现,具体实现应该依赖于抽象。

里式替换原则:父类的调用同样适用于子类。

接口隔离原则:多采用实现各种功能的多个专业接口比只使用一个通用接口更好。

OO编程思维的理解

下面语句摘自百度百科关于面向对象内容:“面向对象(Object Oriented)是软件开发方法。面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物。”按照我的理解,便是我们通过实例化对象来表示真实世界中的各个个体,个体有着各种不同的性格、行为相应对应着对象有着不同的属性、方法。概念的事物都会有些空洞,下面来举一个例子:比如我们需要建造一栋建筑,这个时候我们便可以抽象出一个类,这个类代表建筑这一大类,相对应于房屋建造中的设计图,设计图中包含了设计师对这栋建筑的一些基本特征——建筑风格、墙体设计、房屋走向等,也就是说这个类提供了建筑的大体情况;那么接下来的便是在这个类下实例化对象,每个对象都有自己的特点,在实际情况下便是建筑的一些细节东西由屋主人自行决定,比如里面的家具摆放、各个房间谁来住、屋子的所处位置等等;那么通过这些不同对象则可以很方便地处理现实世界中的各种情况,这便是面向对象的优点所在。

面向对象的三大特性:封装、继承、多态

封装:对象基本上应该是封装的,对象保护并管理着自己的信息,其他对象不可直接访问这个对象的相关属性,不可直接修改这个对象的状态方法等;唯一能够对这个对象进行修改的方式是调用该对象的相应方法来完成。这样可以大大提高其安全性。

继承:继承是一种机制,可以在一个类的基础上创建新类,创建的新类又可再创建更多的类,这样形成的类是一层一层的,而这些在一个类基础上形成的类叫做其子类,基础类叫做父类,子类可以继承父类的属性和方法;这样可以减少类似代码的重复性,提高代码的复用性。

多态:多态是一种思想,指不同的对象收到同一个“信息”会做出不同的回应与结果,这里的“信息”即函数、操作、过程等;其在处理多个对象情况下有很大用处。

 

3. 测试的理解与实践

①测试对于编码质量的重要性

测试是指对一个程序进行不同的输入,再检查程序输出是否符合我们预期的正确结果,在这一过程中便可以发现问题与错误,最后再对程序进行修改。可以看出,测试对于一个程序以及编码质量是很重要的,假如你给用户一个未经完整测试的程序进行使用,用户很可能在各种使用场景下发现各种各样的bug,这对用户的使用体验是大打折扣的;再说编码质量,一个错误越早测试出来越早解决越好,此时花费的时间较少,如果早期的一个错误没有发现,到后期代码编写差不多完成的时候再发现,此时这个错误可能会一直伴随着你后面写的代码,这样修改起来就会很费力了。

②假如让你设计测试用例,你会如何做

尽可能的使用更多的测试用例,当然了,这些测试用例应该经过精心的挑选,比如对一个步骤采用不同的方式进入测试、边界值测试、数值测试(包括较小的数值,正常数值,大型数值)、输入格式错误测试、各项功能测试等等;总之,我们可以多将自己想象成 用户,站在他们的角度去进行测试,虽然经过测试不能保证消除了程序的所有错误,但是能够尽可能的减少错误,不至于让用户发现如此多错误。

4. 课程收获

java这门专业课的收获还是很大的,相比于面向过程的c语言我更喜欢面向对象的java,虽然从面向过程思维转向面向对象思维比较痛苦,但是随着后面的学习我相信能够更加深入理解面向对象的 ,因为面向对象更符合我们人类的思维方式,能够将复杂的事物简单化;(万物皆可为对象,new一个新对象~)

5. 对课程的建议

 课程建议的话好像没啥,任课老师讲的挺好的,上课+课堂作业的授课方式也不错,pta作业有针对性,只是还没见识过大作业的威力。。。

6.之后一阶段的学习计划

能够更好得理解面向对象思维,对类有更好的理解,能够合理地设置类 ,将一个复杂问题简单化;更加熟悉java中一些常用类的使用方法。

posted @ 2020-04-05 15:56  搬砖程序员  阅读(306)  评论(0)    收藏  举报