如何两周达到150行Java程序的能力--part 2
第一次课训练营课程打通了有C语言编程通往面向对象编程的道路,然而道路依然会曲折。下图是第二次训练营课程的训练大纲,从第二次开始,每次课首先进行测试。
针对作业1的训练要求,明确定义了13个具体的测试点和相应测试用例,由各位同学各自对自己的程序进行测试,填写测试报告,即测试点通过情况。13位同学(共17位同学选课,占比约76.5%)完成了第一次作业和相应的测试,统计情况如下:
整体来说,呈现出越往后的测试点通过人数越少的趋势。这在我们的预料之中,因为后面的测试点往往难度稍大。其中有6位同学完成的程序通过了全部13个测试点。可喜可贺。
测试点1:插入集合中不包含的字符,检查字符集合中是否包含了该字符。
测试点2:删除集合中不存在的字符,检查是否会报错,且集合内容保持不变。
测试点3:删除集合中存在的字符,检查集合中是否还包含相应的字符。
测试点4~5:替换集合中指定(位置)字符,检查集合类对边界的检查能力
测试点6~8:在指定位置插入字符,检查边界保护能力。
测试点9~10:字符搜索测试
测试点11:字符排序测试
测试点12:测试字符集合的服务计数能力
测试点13:交集测试。
统计显示,后面几个测试点的通过情况不乐观。反映的问题主要集中于对象属性的更改维护和基本的算法能力,也有Java语言不熟悉有关。
本次课程的核心内容是通过任务来介绍和掌握面向对象一个核心概念,接口。在Java语言中,接口是一种行为抽象机制,使用interface来专门进行定义,每个接口可以包括一系列操作。从设计角度来看,接口用来提取和抽象一组类的共性行为。接口和类之间具有实现关系(implements),一旦一个类实现了某个接口,则可以使用该接口(类型)来来引用相应类的对象,从而建立了仅从行为角度出发的抽象层次。举例如下:
假设有接口Movable,它抽象了若干移动操作,如forward(前进), backward(倒退), left(左转), right(右转)等。同时我们还有类Bicycle,Car,Dog,Cat。我们可以让这四个类都实现Movable接口,这样这四个类具有了共性行为,即都能够前进、倒退、左转、右转。
课堂中我们提前准备好了几个几何体类,通过任务1和任务2来介绍如何构造具体的几何体对象,并分别操纵这些对象来完成体积计算、求和、寻找最大体积和输出等功能。这些功能在算法上都很平凡,但是代码量可不小,而且随几何体对象个数呈线性倍数增长,有很多冗余的代码。这时我们提出的问题是,如何消除这些冗余代码,采用一种一致、简洁的方式来操纵所定义的数据对象。这里有两个关键要点需要分析和讨论:
(1)必须要对不同的几何体对象进行归纳和抽象。抽象是面向对象的一个核心机制,抽象形成层次,解除不必要的耦合。产生冗余代码的主要原因往往是未能进行抽象提取,之所以是冗余,说明有共性成分存在,但是又必须作用于具体不同的对象。从这个要点出发,我们确定要对若干个几何体对象进行抽象。涉及两个小的要点,必须使用一个通用的抽象对象来表示不同的具体几何体对象;必须对不同几何体对象进行抽象。
(2)不同的几何体对象有哪些共性特征可供抽象。这个问题是应用接口和继承机制的难点,抽象不当会导致程序难以理解,容易出错。一般而言,对类进行抽象就是两个维度,数据抽象和行为抽象。观察和分析几个几何体类的数据属性,可以发现共性成分很少,抽象带来的效益低;观察这几个类的行为则发现共性成分显著,比如都能够计算体积,都能查询体积。因此,我们确定了对行为进行抽象,而正是接口这种抽象机制的要义。它是一种脱离对象具体数据特征的行为抽象机制,关注不同对象的共性操作能力,可以很好的隐藏数据带来的差异化。
通过上述两个要点的分析和讨论,我们顺利引入Java的接口机制来改造相应的几何体类,从而能够在主类main方法中使用接口类来声明相应的抽象对象,从而使用统一的方式来访问和管理具体的几何体对象。顺利消除了冗余代码。至此,同学们很好的理解了接口机制的由来和所能解决的问题,以及解决问题时要关注的问题。
任务4相对独立,训练通过控制台的输入处理。意在为后面的正则表达式做铺垫。