之前布置的三角形面积编程题中,有一道选做要求改写两个JavaBean类。这两个类的内部结构和方法实现不一样,但是它们具有相同的方法签名(除了方法体{...}
以外的部分,都是方法签名)。
在上节课作业的基础(如果没有完成,可以参考课件附带的版本)上,编写一个函数,比较两个三角形的面积。第一个三角形大于第二个则输出true
,否则输出false
。注意,该函数必须接受至少两种三角形
我们先用三边长定义的三角形来编写函数:
static boolean compareTo(TriangleEdge tri1, TriangleEdge tri2){
return tri1.getArea() > tri2. getArea()
}
如果需要用点线距和两边长定义的三角形来编写上述函数,那么就要添加三个不同的函数签名:
static boolean compareTo(TriangleEdge tri1, TriangleHeight tri2){/*...*/}
static boolean compareTo(TriangleHeight tri1, TriangleEdge tri2){/*...*/}
static boolean compareTo(TriangleHeight tri1, TriangleHeight tri2){/*...*/}
如果继续添加其他方式定义的三角形,就要添加更多的方法。观察一下这些方法,它们仅仅是参数类型不同,而这些类型都有getArea
方法(以及JavaBean定义的其他所有方法),同时比较面积的方法只调用了getArea
方法。更改参数类型的限制就变得理所当然。
static boolean compareTo(Object tri1, Object tri2){
return tri1.getArea() > tri2. getArea()
}
上述代码必定无法通过编译,原因是Object是最宽泛的对象,不一定会有getArea
方法。另一种方法是类型转换,此处不详细介绍。此时就要引入接口,来告诉面积比较函数这个参数具有getArea
方法。用Triangle
接口来描述具有面积的三角形:
interface Triangle{
double getArea();
double getBaseEdge();
double getSecondEdge();
double getThirdEdge();
}
class TriangleEdge implements Triangle{/*...*/}
static boolean compareTo(Triangle tri1, Triangle tri2){/*...*/}
在上面的代码中,interface
关键字用于定义接口,而implements
关键字说明这个类符合接口的定义(也就是类实现了接口)。定义接口后,就可以保证面积比较函数的三角形参数必然有访问面积的方法,同时不用限制三角形的构造方式。
接口可以限制函数参数或局部变量的结构,能不能限制接口的结构?用extends
关键字(扩展)来说明接口的结构,扩展接口就意味着包含另外一个接口的所有方法。如果要在四边形、三角形、圆形之间比较面积,就需要再定义一个面积接口:
// 闭合的平面形状
interface ClosedPlaneShape{
double getArea();
}
interface Circle extends ClosedPlaneShape{
double getRadius();
}
interface Square extends ClosedPlaneShape{
double getBase();
}
interface Triangle extends ClosedPlaneShape{
double getBaseEdge();
double getSecondEdge();
double getThirdEdge();
}
static boolean compareTo(ClosedPlaneShape tri1, ClosedPlaneShape tri2){/*...*/}
类似于现实世界的分类,implements
和extends
描述了对象的分类。一般把implements左边的类型称为子类,而右边的类型称为父类。
类型图能用来来描述分类关系。这个类型图描述了能够比较面积的平面形状。从父类分出几个分支,而这些分支就是子类。
对于本课程涉及的类型图而言,父类在上子类在下。方框代表类,而圆框代表接口。
之前我们提到过文档注释的语法。只要某个程序包(软件、库、IP核)被复用,那么就需要文档来说明,这个程序包提供了什么功能。文档需要说明,这个程序包包含哪些函数,每一个函数接受什么样的输入,会产生什么现象,反馈给调用者的又是什么结果,能否重复调用等等。
传统的做法是,将文档和程序分开编写,文档存储在专门的文件里,尽管这种方法便于导出用户手册,但是无法对照着看文档和程序,修改程序的同时也不容易更新文档,会给目前(2022年)的版本控制系统带来麻烦。本节课会提到文档注释和javadoc,这种方法是把文档作为函数等的注释,同时写在代码文件里,这种方法可以同时记录代码和文档的改动,但是非常难处理复杂的格式。
文档注释是特殊的注释,这种注释通常写在变量、函数、类等的定义前方。文档注释里有一系列特殊的标记:
/**
* 比较两个三角形的面积,第一个三角形面积较大则返回true,反之返回false
* @param tri1 第一个三角形
* @param tri2 第二个三角形
* @return
* @throws AreaException 三角形三边关系不满足三角形条件时抛出
*/
static boolean compareTo(Triangle tri1, Triangle tri2){/*...*/}
javadoc是Java默认的文档生成程序,会根据文档内的特殊标签来扫描注释,然后生成HTML格式的文档。其他工具也会识别这些特殊标签。
如果某个包具有相似的特征,就可以添加包文档。包文档位于package-summary.java
文件内:
/**
* 测试流的例程
*/
package stream;