OO的第二次博客作业

   在第二次博客作业中,我们进一步学习了继承与多态-JAVA学习的基石,同时也是JAVA三大特性中的两大特性,可以说是十分重要。如果处理好继承与多态,将会大大减少代码的冗杂性,减少代码的复用性,提升效率。同时类与类的继承关系也是实现多态性的前提。


 

  •   关于继承性的一点理解:

继承性(关键词:extends):继承就像一个分水岭,子类从父类继承方法得到父类相同的行为,可以将一件事物分成好多层(即是类)来划分等级,举个最简单的例子,就像生物界中的动物关系一样。  

         

兔子类与羊类都属于食草动物类,老虎类和豹子类属于食肉动物类,食草动物和食肉动物属于动物类(父类)。从动物类来看,它们都属于动物,都具有动物的一般性质,但食草动物和食肉动物各自具有自身特点(吃草和吃肉-即子类特性),食草动物和食肉动物下的其他动物也是有也同样有自身子类特性。

而JAVA中支持的继承方式为单继承或多重继承(注意:JAVA并不支持多继承,并且不论是单继承与多重继承都会提高类之间的耦合度,使代码的独立性变差,)。同时也需要知道子类只能拥有父类中非private的属性和方法,该特性在第4-6次题目集中都有体现(具体分析见下文)

 


  • 对于前三次作业的概括:

    一、第四次题目集:

  1. 本次题目集是对继承的考察,7-2的日期问题(聚合一)及7-3的图形继承都是对继承的进一步实现。第四次题目集整体题量不大,但是7-1水文数据校验中,正则表达式的使用是一个不小的困难,当时刚刚接触正则表达式,没看懂具体用法,只会使用一些简单的正则表达式来判断自然数或者一些固定值,无法满足7-1需求,存在遗憾。
  2. 对于题目7-2,题目已经给出类图,只需要根据类图设计一步步推进程序,只需要在DateUtil类中,进行完善。同时我也认识到PowerDesigner的使用对于软件工程设计与开发的重要性。
  3. 题目集7-3是通过继承关系来计算图形物体的面积和体积,用到了一些简单的数学公式。本题整体不是很复杂,只是其中的面积关系的继承稍微有些兜圈子,让我在这道题上花了不少时间。
  4. 第四次题目除了第一题难度较大,第二题和第三题并不是特别困难,只是对继承关系进行使用,不存在算法的困难,但是在问题的实现上仍然存在理解偏差,导致编写速度缓慢。

 

 、第五次题目集:

  1. 本次题目集共五道题,题型从易到难。有对输入的单词进行排序和合并数组和排序,也有统计关键词和对题目集四中 7-2日期问题面向对象设计(聚合一)的类图改变(聚合二)。整体难度适中,第四题(对JAVA中关键字筛选)为题目集难点,仍然是正则表达式使用很困难,所以导致题目的完成度不高。
  2. 前三题中第一题和第二题均为简单语法复习,无需多言。第三题的形式很好,通过三种JAVA中常用的排序方式输出程序,答案一致,计算机内部运算过程却不一样,这就启发了学生在对程序内部事物进行排序时,对三种不同的排序方式如何选择。希望之后的题目集还能再次见到类似启发性的题目。
  3. 本次题目集中,所占分数最大的题目7-5(聚合二),是此次作业中最重要的题目,仍然是类间关系的调用继承,只不过区别于聚合一,各个类间的关系发生了改变,内部数据的处理也发生了改变。虽然两道题中类相同,但类间关系不同,所以两个程序输入同样的数据答案一样,但各有优劣,这一点将在下面进行分析。

 

三、第六次题目集:

  1. 第六次题目集中共有六道题,三道题目都是对于正则表达式的初步理解,和简单语法的使用。例如对QQ号校验或学号校验,有一道题也是老生常谈的字符串排序,五题六题分值和难度都大于前几道题,考察了JAVA的继承性和多态性。
  2. 第二题是对于字符串的排序,题目给出要求不能使用if语句进行排序(if语句可以写,但多个if语句的使用会使得整个程序的复杂度提升,程序效率低),因此选择了用Arrays类中的 Arrays.sort()对数组中的所有元素进行排序,(我发现该方法并不只针对数字可以进行排序,也可以对字母的顺序进行排序。)
  3. 题目五中的图形继承与多态、题目六中的实现图形接口及多态性与之前题目集四中的图形继承有所关联,循序渐进,引导了学生对于封装-继承-多态性的思考。

 

 


 

  • 关于正则表达式的使用

    正则表达式是一个强大的字符串处理工具,可以对字符串进行查找、提取、分割、替换等操作,是一种可以用于模式匹配和替换的规范。我理解它可以用来检测用户输入的文本是否符合编程者希望的规则。

 题目集中三道题对于正经表达式的简单使用,例如对于数字1-9的校验可以使用 [1-9]来进校验,对于四位数字的可以使用[0-9]{4}来进行校验,过多的复杂正则表达式的使用并未记住,需要上网寻找有关JAVA的正则表达式语法介绍来进行使用。

正则表达式是一个强大的校验工具,C语言中写很多句的if else语句都无法判断的条件,在JAVA中使用正则表达式可以很轻易的判断输入规则是符合要求,达到事半功倍的作用。 

 


  •  设计与分析

一、关于日期问题面向对象设计(聚合一和聚合二)的优劣比较

     对于题目集4(7-2)聚合一、题目集5(7-4)聚合二,程序目的均为完成求下N天,求前N天和求两个日期相差的天数的功能,但其中两个类间调用关系不一样,下面给出聚合一类图

 聚合二类图:

 

 

对比两个类图不难发现两个程序类间关系,聚合一采用的是year单一聚合month,month单一聚合day,day单一聚合DateUtil;聚合二采用的是year、month、day分别聚合DateUtil,那么此时提出一个思考,产生同一结果的两个程序究竟哪个效率更高?

 首先给出两个程序类图:

聚合一:

聚合二:

 

两个程序的整体结构都总体来看都差不多(代码行数359和389,类的数量都一样):

1.比较两个程序的最大复杂度均为6。

2.对于平均复杂度聚合一1.91 略微低于聚合二 1.95。

3.聚合一中Method per Class 为11.25,聚合二中的Method per Class 为10.75.

粗略看数据好像比较不出两个程序运行效率,而且两个程序的SourceMonitor的生成报表内容也基本一致(因为两个程序本就是实现同一个目的,且两程序中类一致,只是调用方式不一致

但仔细思考两个程序的类图中各个类的调用关系,并不难推测出聚合二的整体运行效率更高,因为对于题目需求来说功能需求是求出下N天、前N天和求两天差。

 

  • 从无关计算机的逻辑上来说

      求取的答案均与天有关,所以尽量使各个类间的最小单位与天相关,优先使用Day类,再使用month类,最后才考虑使用year类。

  • JAVA语法中的类间关系来看:

      聚合一中是由Year单一聚合Month,Month单一聚合Day,Day聚合DateUtil;

      聚合二中则是Year,Month,Day分别聚合DateUtil。

        显然在程序判断时,(对于聚合二)如果能提前在Day中计算出整个答案,则不需要走过year,month,直接从Day→DateUtil来得出答案;

  (对于聚合一)无论是否需要判断输入的日期是否在同一年,非同一年同一月等多种情况,都需要走完Year→Month→Day→DateUtil整个路径,必然会加大整个程序运行时间。

对于聚合过多会:提高类之间的耦合度→是代码间关系过于紧密→使得代码的独立性变差。

按照常理来说两个程序均应该有好有坏,但我并未发现聚合一中的优势,应该是因为测试数据的补充不够所造成的。

 

关于聚合————聚合是关联关系的一种特例,是强的关联关系。它体现的是整体与部分的关系,即has-a的关系。此时整体与部分之间是可分离的,它们可以具有各自的存在,部分可以属于多个整体对象,也可以为多个整体对象共享。类似计算机与CPU和风扇的关系或者学校与老师和学生的关系,单一拆分可以存在,但计算机和学校必然是“大于”后者的整体。

 

 

二、关于题目集4(7-3)、题目集6(7-5、7-6)三种渐进式图形继承设计的思路与技术运用(封装、继承、多态、接口等)

  三次题目集中一共出现了三次图形继承问题,涉及到了封装继承多态三大特性,也是初次接触到了之前未接触到的接口。

  • 关于封装性———三次图形继承问题中的变量均设置为private,用户只能看到对象的封装界面信息,对象的内部细节对用户是隐蔽的(封装性的实现),举个例子:题目集四中的7-3图形继承,类Rectangle,继承自Shape(width和length均为私有,不可被外界访问);类Box,继承自Rectangle(height为私有性,不可被外界访问)。起初在刚刚学习封装性时,不太理解封装性的用法,觉得很麻烦,本来public可以通用,改成private后许多其他类无法调用private的变量,但后续思考后发现,private类型有效保护了用户信息,在账号账户信息类的使用是必不可少的,对于网站后台的数据也是必不可少的(将用户与对象的使用者和设计者分割开,使用者不必知道行为实现的细节,只需使用设计者提供的消息来访问对象)
  • 关于继承与多态———三道题目中继承和多态是本次考察的重点,三次题目中也多次使用了继承关系,继承是使新的类获得已有类(父类)的属性和行为,而多态是指一个程序中同名的不同方法共存(简单的理解就是对象在不同情况下的不同表现)。两个关系的目的都是为了使代码复用率降低,使程序结构清晰,降低代码的维护工作量。

   (思考点:对于开启了解多态应该就是刚刚接触JAVA真正开始抽象的部分。)

  •     关于新学到的接口:第一次接触到了接口这个知识点,但只是在7-6中使用了一下,并没有深入了解。我理解的接口就像一个容器,容纳抽象方法的集合,但并不是类,接口是要包含类实现的方法。

 

 对应到本次作业题目集六7-5 “图形继承与多态”中,Circle、Rectangle及Triangle分别继承Shape类,共同可以使用Shape中getArea()和validate()方法。本次作业我们采用的是抽象类定义、实体类构建的方式。即 Shape 为抽象类,Circle、Rectangle 及 Triangle 为实体类。

 

下面给出三次图形继承关系的类图和复杂度分析图

  • 第四次题目集7-3类图及复杂度:

 

 

 

 

 

  •  第六次题目集7-5类图及复杂度:

 

 

 

 

 

  •  第六次题目集7-6类图及复杂度:

  

 

 

 

 


 

  •  对于JAVA集合框架应用的分析总结

   

  • 接口:是代表集合的抽象数据类型。例如 Collection、List、Set、Map 等。之所以定义多个接口,是为了以不同的方式操作集合对象

  • 实现(类):是集合接口的具体实现。从本质上讲,它们是可重复使用的数据结构,例如:ArrayList、LinkedList、HashSet、HashMap。

  • 算法:是实现集合接口的对象里的方法执行的一些有用的计算,例如:搜索和排序。这些算法被称为多态,那是因为相同的方法可以在相似的接口上有着不同的实现。

 

 

 

 

 

 

个人理解:集合可以看作是一种容器,用来存储对象信息。所有集合类都位于java.util包下

 


 

踩坑心得:

  1. 本次作业中,题目集六7-5 图形继承与多态给我带来了很大的麻烦,在通过测试点时,三角形属性测试非法和正常值测试无法同时满足,总是两个测试点只能通过一个,

 

 在程序中,我改进了三角形属性测试(数值小于 0 以及三角形三边关系:两边之和大于的三边)

1 public boolean validate() {
2         if (side1 + side2 > side3 && side1 + side3 > side2 && side2 + side3 > side1  && side1 > 0 && side2 > 0&& side3 > 0) {
3             return true;
4         } else {
5             return false;
6         }
7     }

 

得出测试结果如上图所示,经过多次调试程序,也只能完成一个测试点,无法使程序完全正确。

 最终我只能舍弃掉对于三角形属性非法的测试点,存在遗憾。

2.在对于7-5中的ArrayList的使用存在疑惑:

对于7-5给出的设计要求之一是

ArrayList可理解为动态数组,是JAVA中不可或缺的一部分,开始我理解他与普通数组并没有区别,在使用时候才发现,ArrayList并没有固定大小限制,可以进行添加或者删除元素。

并且在我刚刚使用时打出ArrayList<Shape>程序会报错,只有在导入

import java.util.ArrayList;
后才可以使用。
而且ArrayList中有许多方法非常有用,例如add(),get(),等等,在本题中我应用到了add()来添加每次用户输入的图形类型及其初始数据——来计算图形面积等。

下面是7-5中使用到有关ArrayList的代码:
        if (a >= 0) {
            for (int i = 0; i < a; i++) {
                Circle q = new Circle(sc.nextDouble());

                if (!q.validate()) {
                    System.out.println("Wrong Format");
                    System.exit(0);
                }
                arrayList.add(q);
            }
        }
        if (b >= 0) {
            for (int i = 0; i < b; i++) {
                Rectangle w = new Rectangle(sc.nextDouble(), sc.nextDouble());
                if (!w.validate()) {
                    System.out.println("Wrong Format");
                    System.exit(0);
                }
                arrayList.add(w);
            }
        }
        if (c >= 0) {
            for (int i = 0; i < c; i++) {
                Triangle e = new Triangle(sc.nextDouble(), sc.nextDouble(), sc.nextDouble());
                //if (!e.vaildate()) {
                    //System.out.println("Wrong Format");
                    //System.exit(0);
                //}
                arrayList.add(e);
            }

 

 小结:在之后的编程中一定会使用到ArrayList,其中多多使用set(),get(),add(),remove()会使程序简单快速。提升程序运行效率,避免代码耦合度过大。
3.另外一点,题目难度主要集中于日期问题(聚合一)和(聚合二),在聚合一中需要初次构建出类内部的结构,对于初次接触这方面,有些困难,等到了聚合二时这种情况明显有所好转。  



 

改进建议:

 代码需要改进的地方主要是两点:

  • 题目集五7-4 统计Java程序中关键词的出现次数 题目中,正则表达式使用困难,导致题目无法入手。
  • 题目集六7-5 题目对于三角形属性校验算法有待改正。

 


 

关于本次作业——作业总结:

在这三次题目集中,我学习到了继承和多态的具体使用,解决了图形聚合设计问题和日期聚合设计问题。了解了一些新知识,例如接口,ArrayList中的方法,插入排序方法,和简单的正则表达式的使用,等等。

但我同时也发现自己对于继承的理解不够到位,对于动态数组的使用不够熟练,尤其是对于正则表达式的使用缺乏认识,很片面,也很不足,希望在今后的学习之路中继续学习并熟练掌握这些知识点,并可以运用到程序内。

目前而言,就我自身最大的缺点仍然是无法对程序结构清晰的掌握,这种能力需要在之后的学习生涯逐步加强!

对于程序的编写中,类图的设计决定一个程序的好坏,因此熟练地使用Powerdesigner对于软件开发者来说很重要,就像有了地图的寻宝者一样,可以做到事半功倍的作用。

 

本单元的题目集目的性很明确———对于继承和多态性的掌握

希望下个单元老师将带来更能启发我们思维的题目!

 

 

 

 

 

 

 

 

 

posted on 2021-05-01 01:42  晨_之曦  阅读(92)  评论(0)    收藏  举报

导航