Java实验8《抽象类和接口》

本是古典 何须时尚 2021-11-23 02:16 427阅读 0赞

一、实验目的

  1. 设计和使用抽象类
  2. 定义接口以及实现接口的类
  3. 理解接口继承和多态

二、实验内容

  1. (P455,13.1)【三角形类】设计一个扩展自抽象类GeometriObject的新的Triangle类。绘制Triangle类和GeometricObject类的UML图并实现Triangle类。编写一个测试程序,提示用户输入三角形的三条边、一种颜色以及一个表明该三角形是否填充的布尔值。程序应该根据用户的输入,使用这些边以及颜色和是否填充的信息,创建一个Triangle对象。程序应该显示面积、周长、颜色以及真或者假来表明是否被填充。

 1.1 UML图
Alt

 1.2 程序代码:
(1)program1源程序

  1. //program1源程序
  2. import java.util.Scanner;
  3. public class program1 {
  4. public static void main(String[] args){
  5. Scanner input = new Scanner(System.in);
  6. boolean continueInput = true;
  7. while(continueInput){
  8. //输入三角形的三条边
  9. System.out.print("请输入三角形的三条边长:");
  10. double side1 = input.nextDouble();
  11. double side2 = input.nextDouble();
  12. double side3 = input.nextDouble();
  13. //判断三条边是否构成三角形,能够成则继续,反之则重新输入
  14. if((side1+side2>side3) && (side1+side3>side2) && (side2+side3>side1)){
  15. //输入三角形的颜色
  16. System.out.print("请输入三角形的颜色:");
  17. String color = input.next();
  18. //输入三角形是否填充
  19. System.out.print("请输入三角形是否被填充(true为1/false为0):");
  20. int fill = input.nextInt();
  21. GeometricObject triangle = new Triangle(side1, side2, side3);
  22. triangle.setColor(color);
  23. boolean filled;
  24. if(fill==0)
  25. filled=false;
  26. else
  27. filled=true;
  28. triangle.setFilled(filled);
  29. System.out.println(triangle.toString());
  30. continueInput = false;
  31. }
  32. else
  33. System.out.println("输入有误,这三条边不能构成一个三角形。\n");
  34. }//while结束
  35. }//main方法结束
  36. }//class结束

(2)Triangle类程序

  1. //Triangle类程序
  2. public class Triangle extends GeometricObject {
  3. private double side1;
  4. private double side2;
  5. private double side3;
  6. //创建无参构造方法
  7. public Triangle(){
  8. side1 = 1.0;
  9. side2 = 1.0;
  10. side3 = 1.0;
  11. }
  12. public Triangle(double side1, double side2, double side3){
  13. this.side1 = side1;
  14. this.side2 = side2;
  15. this.side3 = side3;
  16. }
  17. public double getSide1(){
  18. return side1;
  19. }
  20. public double getSide2(){
  21. return side1;
  22. }
  23. public double getSide3(){
  24. return side1;
  25. }
  26. public void setSide1(double side1){
  27. this.side1=side1;
  28. }
  29. public void setSide2(double side2){
  30. this.side2=side2;
  31. }
  32. public void setSide3(double side3){
  33. this.side3=side3;
  34. }
  35. public double getArea(){
  36. //平均边长s
  37. double s = ( side1 + side2 + side3 ) / 2.0;
  38. //计算面积
  39. return Math.sqrt( s * (s-side1) * (s-side2) * (s-side3) );
  40. }//getArea结束
  41. public double getPerimeter(){
  42. return side1+side2+side3;
  43. }
  44. @Override
  45. public String toString(){
  46. return "\narea: " + getArea() + "\tperimeter: " + getPerimeter()
  47. + "\ncolor: " + super.getColor() + "\tfilled: " + super.isFilled();
  48. }
  49. }//Triangle类结束

(3)GeometricObject类源程序

  1. //GeometricObject类源程序
  2. public abstract class GeometricObject {
  3. private String color = "white";
  4. private boolean filled;
  5. private java.util.Date dateCreated;
  6. //无参构造函数
  7. protected GeometricObject(){
  8. dateCreated = new java.util.Date();
  9. }
  10. protected GeometricObject(String color, boolean filled){
  11. dateCreated = new java.util.Date();
  12. this.color = color;
  13. this.filled = filled;
  14. }
  15. public String getColor(){
  16. return color;
  17. }
  18. public void setColor(String color){
  19. this.color = color;
  20. }
  21. public boolean isFilled(){
  22. return filled;
  23. }
  24. public void setFilled(boolean filled){
  25. this.filled = filled;
  26. }
  27. public java.util.Date getDateCreated(){
  28. return dateCreated;
  29. }
  30. @Override
  31. public String toString(){
  32. return "created on " + dateCreated + "\ncolor: " + color +
  33. " and filled: " + filled;
  34. }
  35. public abstract double getArea();
  36. public abstract double getPerimeter();
  37. }//GeometricObject类结束

  1.3 运行结果与分析:
在这里插入图片描述
    运行正确,符合要求,提示用户输入三角形的三条边、一种颜色以及一个表明该三角形是否填充的布尔值。程序显示面积、周长、颜色以及真或者假来表明是否被填充。

  1.4 心得体会:
    此程序为抽象类的基本运用,注意UML图中抽象类名与抽象方法使用斜体表示,父类中定义抽象方法,子类中实现抽象方法即可,其他操作与一般类一样。


  1. (P456, 13.6)【ComparableCircle类】创建名为ComparableCircle的类,它继承自Circle类,并实现Comparable接口。画出UML图并实现compareTo方法,使其根据面积比较两个圆。编写一个测试程序求出ComparableCircle对象的两个实例中的较大者。

 2.1 UML图
在这里插入图片描述

 2.2 程序代码:
(1)program2源程序:

  1. //program2源程序:
  2. import java.util.Scanner;
  3. public class program2{
  4. public static void main (String[] args){
  5. Scanner input = new Scanner(System.in);
  6. //输入两个圆的半径
  7. System.out.print("请输入两个圆的半径:");
  8. double radius1 = input.nextDouble();
  9. double radius2 = input.nextDouble();
  10. //创建两个圆
  11. ComparableCircle circle1 = new ComparableCircle(radius1);
  12. ComparableCircle circle2 = new ComparableCircle(radius2);
  13. int compara = circle1.comparaTo(circle2);
  14. //比较两个圆的面积大小,输出结果
  15. if(compara > 0)
  16. System.out.println("circle1 > circle2");
  17. else if(compara == 0)
  18. System.out.println("circle1 = circle2");
  19. else
  20. System.out.println("circle1 < circle2");
  21. }
  22. }//class结束

(2)ComparableCircle类源程序:

  1. //ComparableCircle类源程序
  2. public class ComparableCircle extends Circle
  3. implements Comparable<ComparableCircle> {
  4. public ComparableCircle(double radius){
  5. super(radius);
  6. }
  7. //实现comparaTo方法
  8. public int comparaTo(ComparableCircle o){
  9. if(getArea() > o.getArea())
  10. return 1;
  11. else if(getArea() == o.getArea())
  12. return 0;
  13. else
  14. return -1;
  15. }
  16. }//calss结束

(3)接口Comparable源程序:

  1. //接口Comparable源程序
  2. public interface Comparable<ComparableCircle>{
  3. public int comparaTo(ComparableCircle o);
  4. }

(4)Circle类源程序:

  1. //Circle类源程序
  2. public class Circle{
  3. public static final double PI = 3.14159;
  4. private double radius;
  5. public Circle(){
  6. radius=1.0;
  7. }
  8. public Circle(double radius){
  9. this.radius=radius;
  10. }
  11. public double getRadius(){
  12. return radius;
  13. }
  14. public void setRadius(double radius){
  15. this.radius=radius;
  16. }
  17. public double getArea(){
  18. return PI*radius*radius;
  19. }
  20. public double getPerimeter(){
  21. return PI*radius*2;
  22. }
  23. }//class结束

  2.3 运行结果与分析:
Alt
    运行正确,符合题目要求,比较给定半径的两个实例圆,输出较大者。

  2.4 心得体会:
    此程序是接口的初步运用,最主要是几个类之间的调用关系要分清楚,以及接口中只有抽象方法的定义,抽象方法实现在具体类中。


  1. (P456,13.7)【可着色接口Colorable】设计一个名为Colorable的接口,其中有名为howToColor()的void方法。可着色对象的每个类必须实现Colorable接口。设计一个扩展GeometricObject类并实现Colorable接口的名为Square的类。实现howToColor方法,显示消息“给所有的四条边着色”。
    画出包含Colorable、Square和GeometricObject的UML图。编写一个测试程序,创建有五个GeometricObject对象的数组。对于数组中的每个对象而言,如果对象是可着色的,那就调用howToColor方法。

 3.1 UML图
在这里插入图片描述

 3.2 程序代码:
(1)program3的源程序:

  1. //program3的源程序
  2. public class program3{
  3. public static void main(String[] args){
  4. //创建有五个GeometricObject对象的数组
  5. GeometricObject[] geometricObject = { new Circle(),
  6. new Square(), new Rectangle(), new Square(), new Triangle()};
  7. //判断每个对象是否可着色,可以着色则调用howToColor方法
  8. for(int i=0; i<geometricObject.length; i++){
  9. if(geometricObject[i] instanceof Colorable){
  10. System.out.print("geometricObject " + (i+1) + " : ");
  11. ((Colorable)geometricObject[i]).howToColor();
  12. }
  13. }
  14. }//main结束
  15. }//class结束
  16. class Circle extends GeometricObject{
  17. private double radius;
  18. //无参构造方法
  19. public Circle(){
  20. }
  21. }
  22. class Triangle extends GeometricObject{
  23. private double side1, side2, side3;
  24. //无参构造方法
  25. public Triangle(){
  26. }
  27. }
  28. class Rectangle extends GeometricObject{
  29. private double width, height;
  30. //无参构造方法
  31. public Rectangle(){
  32. }
  33. }

(2)Square类的源程序:

  1. //Square类的源程序
  2. public class Square extends GeometricObject
  3. implements Colorable{
  4. private double sideLength;
  5. //无参构造方法
  6. public Square(){
  7. sideLength=1.0;
  8. }
  9. //含参构造方法
  10. public Square(double sideLength){
  11. this.sideLength = sideLength;
  12. }
  13. public void howToColor(){
  14. System.out.println("给所有的四条边长着色");
  15. }
  16. public double getSideLength(){
  17. return sideLength;
  18. }
  19. public void setSideLength(double sideLength){
  20. this.sideLength = sideLength;
  21. }
  22. }//class结束

(3)Colorable接口的源程序:

  1. //Colorable接口的源程序
  2. public interface Colorable{
  3. public void howToColor();
  4. }

(4)GeometricObject类的源程序:

  1. //GeometricObject类的源程序
  2. public class GeometricObject {
  3. private String color = "white";
  4. private boolean filled;
  5. private java.util.Date dateCreated;
  6. //无参构造函数
  7. protected GeometricObject(){
  8. dateCreated = new java.util.Date();
  9. }
  10. protected GeometricObject(String color, boolean filled){
  11. dateCreated = new java.util.Date();
  12. this.color = color;
  13. this.filled = filled;
  14. }
  15. public String getColor(){
  16. return color;
  17. }
  18. public void setColor(String color){
  19. this.color = color;
  20. }
  21. public boolean isFilled(){
  22. return filled;
  23. }
  24. public void setFilled(boolean filled){
  25. this.filled = filled;
  26. }
  27. public java.util.Date getDateCreated(){
  28. return dateCreated;
  29. }
  30. @Override
  31. public String toString(){
  32. return "created on " + dateCreated + "\ncolor: " + color +
  33. " and filled: " + filled;
  34. }
  35. }//GeometricObject类结束

  3.3 运行结果与分析:
在这里插入图片描述
    运行正确,符合要求,对于数组中的每个对象而言,如果对象是可着色的,那就调用howToColor方法。数组geometricObject中的五个对象分别是Circle, Square, Rectangle,Square, Triangle,其中只有对象Square可着色,所以程序运行结果显示数组中的第2个对象和第4个对象可着色,调用howToColor方法,显示消息。

  3.4 心得体会:
    此程序是接口的进一步使用,接口内定义howToColor方法,Square内实现howToColor方法,主程序判断对象是否可着色再确定是否调用。其他即为类的简单使用。


  1. 【附加题,可选做】【找出最大的对象】编写一个方法,返回对象数组中最大的对象。方法签名如下:
    public static Object max(Comparable[] a)
    所有对象都是Comparable接口的实例。对象在数组中的顺序是由compareTo方法决定的。
    编写测试程序,创建一个由10个字符串构成的数组,一个由10个整数构成的数组和一个由10个日期构成的数组,找出数组中最大的字符串、整数和日期。

4.1 程序代码:

  1. import java.util.Date;
  2. import java.text.SimpleDateFormat;
  3. import java.lang.Comparable;
  4. public class program4{
  5. public static void main(String[] args){
  6. String[] a = { "apple","pear","banana","orange","anna",
  7. "spring","summer","autumn", "winter","date"};
  8. Integer[] b = { 1, 8, 5, 4, 2, 3, 9, 7, 6, 2};
  9. //Date中年月日表示为 年:理想年-1900 月:理想月-1 日:理想日
  10. Date date1 = new Date(2018-1900, 6-1, 16);
  11. Date date2 = new Date(2019-1900, 5-1, 26);
  12. Date date3 = new Date(2008-1900, 8-1, 8);
  13. Date date4 = new Date(2009-1900, 7-1, 9);
  14. Date date5 = new Date(2001-1900, 4-1, 3);
  15. Date date6 = new Date(2015-1900, 9-1, 17);
  16. Date date7 = new Date(2020-1900, 12-1, 21);
  17. Date date8 = new Date(2013-1900, 11-1, 11);
  18. Date date9 = new Date(2002-1900, 2-1, 2);
  19. Date date10 = new Date(2014-1900, 1-1, 28);
  20. Date[] c = { date1, date2, date3, date4, date5,
  21. date6, date7, date8, date9, date10};
  22. //规范日期输出形式为:年-月-日
  23. SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd");
  24. //输出三个数组
  25. System.out.print("String: ");
  26. for(String e: a)
  27. System.out.print(e + " ");
  28. System.out.print("\nInteger: ");
  29. for(Integer e: b)
  30. System.out.print(e + " ");
  31. System.out.print("\nDate: ");
  32. //每行5个日期
  33. for(int i=0; i<c.length; i++){
  34. if( (i+1) % 5 == 0){
  35. System.out.println( ft.format(c[i]) + " ");
  36. System.out.print(" ");
  37. }
  38. else
  39. System.out.print( ft.format(c[i]) + " ");
  40. }
  41. //调用max方法,输出每个数组的最大值
  42. System.out.println("\nMax of String : " + max(a));
  43. System.out.println("Max of Integer : " + max(b));
  44. System.out.println("Max of Date : " + ft.format(max(c)) );
  45. }//main方法结束
  46. public static Object max(Comparable[] a){
  47. Comparable max = null;
  48. //先判断每个数组类型,再用comparaTo依次比较选择出最大值
  49. if(a[0] instanceof String){
  50. max = (String)a[0];
  51. for(int i=1; i<a.length; i++){
  52. if(max.compareTo((String) a[i]) < 0)
  53. max = (String)a[i];
  54. }
  55. }
  56. else if(a[0] instanceof Integer){
  57. max = (Integer)a[0];
  58. for(int i=1; i<a.length; i++){
  59. if(max.compareTo((Integer) a[i]) < 0)
  60. max = (Integer)a[i];
  61. }
  62. }
  63. else if(a[0] instanceof Date){
  64. max = (Date)a[0];
  65. for(int i=1; i<a.length; i++){
  66. if(max.compareTo((Date) a[i]) < 0)
  67. max = (Date)a[i];
  68. }
  69. }
  70. return max;
  71. }//max方法结束
  72. }//class结束

4.2 运行结果:
在这里插入图片描述
  程序运行正确,符合输出要求,编译过程有点小问题(解释见心得体会),创建三个不同类型(字符串、整数和日期)的数组,调用max方法求最大值。

4.3 心得体会:
  此程序为主要为Comparable接口的应用,创建三个数组,调用max方法,用instanceof确定数组类型,再用for循环与compareTo方法比较确定最大值,max中需注意数组中元素使用时的及时转换。
编译过程中的问题1:使用已过时API,部分截图见下,Date数组中元素的创建时使用的自定义日期方法已过时。所以为了满足题目要求而使用,不影响程序运行。
在这里插入图片描述
编译过程中的问题2:使用未经检查的操作,部分截图见下,max方法中判断数组类型时只是使用第一个元素进行判定,其他元素未判定。但是,程序在创建数组已确定数组中所有元素均为同一类型,所以此处忽略后续元素的判定,不影响程序运行。
在这里插入图片描述


发表评论

表情:
评论列表 (有 0 条评论,427人围观)

还没有评论,来说两句吧...

相关阅读

    相关 java8之后的接口抽象

    java8 1.接口可以写默认方法(default)和静态方法,好处是当需要对接口进行修改时,在子类中不需要实现而且可以重写默认方法;如果添加的是静态方法,子类可以直接使用

    相关 Java抽象接口

    抽象类是一种功能不全的类,接口是一个抽象方法声明和静态不能被修改的数据的集合,两者都不能被实例化。从某种意义上说,接口是一种特殊形式的抽象类,在Java语言中,抽象类表示一种继

    相关 java接口抽象

    1、抽象类最大的特征就是在普通类的基础上追加了抽象方法,而事实上抽象类定义里面也存在有若干的问题 。将抽象方法和普通方法写在一起有些乱 。抽象类本身会存在单继承的局限

    相关 JAVA抽象接口

    抽象类: 定义一个类的时候,常常需要定义一些方法来描述该类的行为特征,但有时候这些方法的实现方式无法确定。 针对这种情况,Java允许在定义方法的时候可以不写方法体,不

    相关 Java抽象接口

    父类定义了子类中的共同行为,接口定义不同类的共同行为。 抽象类 抽象类不可 new 一个实例,可以包含抽象方法,没有实现,这些方法在子类中实现。 使用 abstrac