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

一、实验目的

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

二、实验内容

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

 1.1 UML图
Java实验8《抽象类和接口》_第1张图片

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

//program1源程序
import java.util.Scanner;

public class program1 {
     public static void main(String[] args){
	Scanner input = new Scanner(System.in);
	boolean continueInput = true;
		
	while(continueInput){
	    //输入三角形的三条边
	    System.out.print("请输入三角形的三条边长:");
	    double side1 = input.nextDouble();
	    double side2 = input.nextDouble();
	    double side3 = input.nextDouble();
  //判断三条边是否构成三角形,能够成则继续,反之则重新输入
	   if((side1+side2>side3) && (side1+side3>side2) && (side2+side3>side1)){
		//输入三角形的颜色
		System.out.print("请输入三角形的颜色:");
		String color = input.next();
		//输入三角形是否填充
System.out.print("请输入三角形是否被填充(true为1/false为0):");
		int fill = input.nextInt();
				
		GeometricObject triangle = new Triangle(side1, side2, side3);
		triangle.setColor(color);
      boolean filled;
      if(fill==0)
            filled=false;
       else
            filled=true;
		triangle.setFilled(filled);
		System.out.println(triangle.toString());
		continueInput = false;
	   }
	   else
	System.out.println("输入有误,这三条边不能构成一个三角形。\n");
	}//while结束
     }//main方法结束
}//class结束

(2)Triangle类程序

//Triangle类程序
public class Triangle extends GeometricObject {
	private double side1;
	private double side2;
	private double side3;
	
    //创建无参构造方法        
    public Triangle(){
         side1 = 1.0;
         side2 = 1.0;
         side3 = 1.0;
    }
    
    public Triangle(double side1, double side2, double side3){
        this.side1 = side1;
        this.side2 = side2;
        this.side3 = side3;
   }
    
    public double getSide1(){
        return side1;
   }
    
    public double getSide2(){
        return side1;
   }
   
    public double getSide3(){
        return side1;
   }
   
    public void setSide1(double side1){
    	this.side1=side1;
    }
    
    public void setSide2(double side2){
    	this.side2=side2;
    }
    
    public void setSide3(double side3){
    	this.side3=side3;
    }
    
    public double getArea(){
        //平均边长s
        double s = ( side1 + side2 + side3 ) / 2.0;
        //计算面积
        return Math.sqrt( s * (s-side1) * (s-side2) * (s-side3) );
    }//getArea结束
 
    public double getPerimeter(){
      return side1+side2+side3;
    }
    
    @Override
    public String toString(){
        return "\narea: " + getArea() + "\tperimeter: " + getPerimeter()
         + "\ncolor: " + super.getColor() + "\tfilled: " + super.isFilled();
   }
}//Triangle类结束

(3)GeometricObject类源程序

//GeometricObject类源程序
public abstract class GeometricObject {
	private String color = "white";
	private boolean filled;
	private java.util.Date dateCreated;
	  
	//无参构造函数
	protected GeometricObject(){
	dateCreated = new java.util.Date();
	}        
	          
	protected GeometricObject(String color, boolean filled){
		dateCreated = new java.util.Date();
	    this.color = color;
	    this.filled = filled;
	}
	          
	public String getColor(){
	    return color;
	}

	public void setColor(String color){
	    this.color = color;
    }
	           
	public boolean isFilled(){
	     return filled;
    }
	    
	public void setFilled(boolean filled){
	     this.filled = filled;
	}

	public java.util.Date getDateCreated(){
	     return dateCreated;
	}

	@Override
	public String toString(){
	      return "created on " + dateCreated + "\ncolor: " + color +
	              " and filled: " + filled;
	}
	
	public abstract double getArea();

	public abstract double getPerimeter();
}//GeometricObject类结束

  1.3 运行结果与分析:
Java实验8《抽象类和接口》_第2张图片
    运行正确,符合要求,提示用户输入三角形的三条边、一种颜色以及一个表明该三角形是否填充的布尔值。程序显示面积、周长、颜色以及真或者假来表明是否被填充。

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


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

 2.1 UML图
Java实验8《抽象类和接口》_第3张图片

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

//program2源程序:
import java.util.Scanner;
public class program2{
    public static void main (String[] args){
    Scanner input = new Scanner(System.in);
    
    //输入两个圆的半径
    System.out.print("请输入两个圆的半径:");
    double radius1 = input.nextDouble();
    double radius2 = input.nextDouble();

    //创建两个圆
    ComparableCircle circle1 = new ComparableCircle(radius1);
    ComparableCircle circle2 = new ComparableCircle(radius2);
    int compara = circle1.comparaTo(circle2);

    //比较两个圆的面积大小,输出结果
    if(compara > 0)
        System.out.println("circle1 > circle2");
    else if(compara == 0)
        System.out.println("circle1 = circle2");
    else
        System.out.println("circle1 < circle2");
    }    
}//class结束

(2)ComparableCircle类源程序:

//ComparableCircle类源程序
public class ComparableCircle extends Circle
      implements Comparable<ComparableCircle> {

     public ComparableCircle(double radius){
        super(radius);
     }

     //实现comparaTo方法
     public int comparaTo(ComparableCircle o){
         if(getArea() > o.getArea())
              return 1;
         else if(getArea() == o.getArea())
              return 0;
         else
              return -1;
     }
}//calss结束

(3)接口Comparable源程序:

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

(4)Circle类源程序:

//Circle类源程序
public class Circle{
    public static final double PI = 3.14159;
    private double radius;

    public Circle(){
        radius=1.0;
    }

    public Circle(double radius){
         this.radius=radius;
    }

    public double getRadius(){
        return radius;
    }

    public void setRadius(double radius){
        this.radius=radius;
    }

    public double getArea(){
        return PI*radius*radius;
    }

    public double getPerimeter(){
       return PI*radius*2;
    }
}//class结束

  2.3 运行结果与分析:
Java实验8《抽象类和接口》_第4张图片
    运行正确,符合题目要求,比较给定半径的两个实例圆,输出较大者。

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


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

 3.1 UML图
Java实验8《抽象类和接口》_第5张图片

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

//program3的源程序
public class program3{
    public static void main(String[] args){
        //创建有五个GeometricObject对象的数组
        GeometricObject[] geometricObject = {new Circle(), 
new Square(),  new Rectangle(),  new Square(),  new Triangle()};
     //判断每个对象是否可着色,可以着色则调用howToColor方法
        for(int i=0; i<geometricObject.length; i++){
            if(geometricObject[i] instanceof Colorable){
                System.out.print("geometricObject " + (i+1) + " : ");
               ((Colorable)geometricObject[i]).howToColor();
            }
        }
    }//main结束
}//class结束

class Circle extends GeometricObject{
    private double radius;
 
    //无参构造方法
    public Circle(){

    }
}

class Triangle extends GeometricObject{
     private double side1, side2, side3;

     //无参构造方法
     public Triangle(){
         
     }
}

class Rectangle extends GeometricObject{
     private double width, height;

     //无参构造方法
     public Rectangle(){
         
     }
}

(2)Square类的源程序:

//Square类的源程序
public class Square extends GeometricObject 
      implements Colorable{
      private double sideLength;
      //无参构造方法
      public Square(){
            sideLength=1.0;
      }
      //含参构造方法
      public Square(double sideLength){
           this.sideLength = sideLength;
      }

      public void howToColor(){
          System.out.println("给所有的四条边长着色");
      }

      public double getSideLength(){
          return sideLength;
      }

      public void setSideLength(double sideLength){
          this.sideLength = sideLength;
      }
}//class结束

(3)Colorable接口的源程序:

//Colorable接口的源程序
public interface Colorable{
     public void howToColor();
}

(4)GeometricObject类的源程序:

//GeometricObject类的源程序
public class GeometricObject {
	private String color = "white";
	private boolean filled;
	private java.util.Date dateCreated;
	  
	//无参构造函数
	protected GeometricObject(){
	dateCreated = new java.util.Date();
	}        
	          
	protected GeometricObject(String color, boolean filled){
		dateCreated = new java.util.Date();
	    this.color = color;
	    this.filled = filled;
	}
	          
	public String getColor(){
	    return color;
	}

	public void setColor(String color){
	    this.color = color;
    }
	           
	public boolean isFilled(){
	     return filled;
    }
	    
	public void setFilled(boolean filled){
	     this.filled = filled;
	}

	public java.util.Date getDateCreated(){
	     return dateCreated;
	}
	@Override
	public String toString(){
	      return "created on " + dateCreated + "\ncolor: " + color +
	              " and filled: " + filled;
	}
}//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 程序代码:

import java.util.Date;  
import java.text.SimpleDateFormat;
import java.lang.Comparable;

public class program4{
     public static void main(String[] args){
        String[] a = {"apple","pear","banana","orange","anna",
                      "spring","summer","autumn", "winter","date"};
        Integer[] b = {1, 8, 5, 4, 2, 3, 9, 7, 6, 2};
 //Date中年月日表示为 年:理想年-1900 月:理想月-1 日:理想日
        Date date1 = new Date(2018-1900, 6-1, 16);
        Date date2 = new Date(2019-1900, 5-1, 26);
        Date date3 = new Date(2008-1900, 8-1, 8);
        Date date4 = new Date(2009-1900, 7-1, 9);
        Date date5 = new Date(2001-1900, 4-1, 3);
        Date date6 = new Date(2015-1900, 9-1, 17);
        Date date7 = new Date(2020-1900, 12-1, 21);
        Date date8 = new Date(2013-1900, 11-1, 11);
        Date date9 = new Date(2002-1900, 2-1, 2);
        Date date10 = new Date(2014-1900, 1-1, 28);
        Date[] c = {date1, date2, date3, date4, date5,
                  date6, date7, date8, date9, date10}; 
        //规范日期输出形式为:年-月-日
        SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd");

        //输出三个数组
        System.out.print("String: ");
        for(String e: a)
            System.out.print(e + " ");
        System.out.print("\nInteger: ");
        for(Integer e: b)
            System.out.print(e + " ");
        System.out.print("\nDate: ");
        //每行5个日期
        for(int i=0; i<c.length; i++){
            if( (i+1) % 5 == 0){
               System.out.println( ft.format(c[i]) + " ");
               System.out.print("      ");
            }               
            else
               System.out.print( ft.format(c[i]) + " ");
        }
        //调用max方法,输出每个数组的最大值
        System.out.println("\nMax of String  : " + max(a));
        System.out.println("Max of Integer : " + max(b));
        System.out.println("Max of Date    : " + ft.format(max(c)) );
     }//main方法结束

     public static Object max(Comparable[] a){
          Comparable max = null;
    //先判断每个数组类型,再用comparaTo依次比较选择出最大值
          if(a[0] instanceof String){
              max = (String)a[0];
              for(int i=1; i<a.length; i++){
                 if(max.compareTo((String) a[i]) < 0)
                     max = (String)a[i];
              }
          }
          else if(a[0] instanceof Integer){
              max = (Integer)a[0];
              for(int i=1; i<a.length; i++){
                 if(max.compareTo((Integer) a[i]) < 0)
                     max = (Integer)a[i];
              }
          }
          else if(a[0] instanceof Date){
              max = (Date)a[0];
              for(int i=1; i<a.length; i++){
                 if(max.compareTo((Date) a[i]) < 0)
                     max = (Date)a[i];
              }
         }
         return max;
     }//max方法结束

}//class结束

4.2 运行结果:
Java实验8《抽象类和接口》_第6张图片
  程序运行正确,符合输出要求,编译过程有点小问题(解释见心得体会),创建三个不同类型(字符串、整数和日期)的数组,调用max方法求最大值。

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


你可能感兴趣的:(Java)