实验三 类和对象
- 实验目的
- 理解Java程序设计是如何体现面向对象编程的基本思想;
- 了解类的封装方法以及如何创建类和对象;
- 了解成员变量和成员方法的特性,掌握OOP方式进行程序设计的方法;
- 实验要求
- 体现面向对象思想;
- 创建对象和使用对象的方法;
- 不同成员变量修饰方法;
- 不同成员方法修饰方法;
- 成员方法中的参数传递规则。
- 实验内容
(1)定义一个Light类,描述灯这一类对象,给Light类增加成员变量的定义,描述有关灯这一类对象的属性“状态”,增加成员方法的定义“开灯”,描述有关灯这一类对象的操作,在main方法中把自定义好的类作为复合数据类型定义变量。在类Light的基础上,增加实例方法的定义,改变对象的实例变量的值,实现灯开或关的动作,改变灯的状态。定义一个带参数的构造方法,在构造方法中实现对象的初始化,另外需要顶一个无参数的构造函数。
(2)定义一个类Rectangle,描述矩形对象以及矩形对象上的操作与运算,矩形的左上角坐标(x1,y1)和右下角坐标(x2,y2)可以确定一个矩形,4个坐标值可以定义成矩形的属性,在类Rectangle中定义不同的方法,实现矩形的如下运算:移动矩形;判断一个点是否在矩形内部;计算并返回与另一个矩形合并后的新矩形;计算并返回与另一个矩形相交后的新矩形,注意没有相交的情况。定义无参构造函数,默认左上角和右下角的坐标都是(0,0),实际是一个点。定义有4个参数的构造方法,分别代表左上角和右下角的坐标。
- 实验总结
- 什么是构造函数?
- 程序中有多个类时如何确定源文件的名称。
1设计思路
(1)定义一个Light类,描述灯这一类对象,给Light类增加成员变量的定义,描述有关灯这一类对象的属性“状态”,增加成员方法的定义“开灯”,描述有关灯这一类对象的操作,在main方法中把自定义好的类作为复合数据类型定义变量。在类Light的基础上,增加实例方法的定义,改变对象的实例变量的值,实现灯开或关的动作,改变灯的状态。定义一个带参数的构造方法,在构造方法中实现对象的初始化,另外需要定一个无参数的构造函数。
设计方法:
按照要求在创建程序文件时定义为Light_Test .java,在主函数中实现初始化以及开灯关灯操作,此处需要按题中要求实现两个实例化方法:无参构造实例化和有参构造实例化,需要调用Light类中的一些函数加以实现!
以下是Light的内容:
- 首先定义public String state; //描述状态的字符变量;
- 进行无参和有参构造;
- 获取状态函数;
- 开灯函数;
- 关灯函数;
- 打印灯的开关信息函数。
在主函数首先使用无参构造实例化L1(初始状态为关),获取其状态并且输出;接着是开灯操作,打印状态;最后是关灯操作,并且打印状态!
(2)定义一个类Rectangle,描述矩形对象以及矩形对象上的操作与运算,矩形的左上角坐标(x1,y1)和右下角坐标(x2,y2)可以确定一个矩形,4个坐标值可以定义成矩形的属性,在类Rectangle中定义不同的方法,实现矩形的如下运算:移动矩形;判断一个点是否在矩形内部;计算并返回与另一个矩形合并后的新矩形;计算并返回与另一个矩形相交后的新矩形,注意没有相交的情况。定义无参构造函数,默认左上角和右下角的坐标都是(0,0),实际是一个点。定义有4个参数的构造方法,分别代表左上角和右下角的坐标。
设计方法:
这题同样需要用到两种构造方法:有参和无参构造:无参构造函数,默认左上角和右下角的坐标都是(0,0);有4个参数的构造方法,分别代表左上角和右下角的坐标,我用double x1,double y1,double x2,double y2 进行表示。
此题需要实现4个功能,以下依次讲解:
- 移动矩形:public void movePoint(double x1,double y1,double x2,double y2) ,需要传入4个变量表示需要移动的方式,用this.x1 += x1(4条)语句实现坐标的移动,并输出移动后的坐标。注意的是this的加入,不能忘记加上this,否则会出错。
- 判断一个点是否在矩形内部:public static boolean isInRectangle(double x1,double y1,double x2,double y2,double x,double y),需要传入6个参数,前4个是目标矩形的位置,后两个是目标点坐标。此处只考虑特殊情况:矩形平行于x轴和y轴,只用4条判断语句即可实现对点(x,y)是否在矩形中的判断。
- 矩形合并:public static void combine(double x1,double y1,double x2,double y2,double x11,double y11,double x22,double y22),需要传入8个参数,分别表示两个矩形的位置,以进行判断,判断过程需要用到三元运算符 “? : ”,并输出合并的矩形位置。
- 矩形相交:public static void intersects(double x1,double y1,double x2,double y2,double x11,double y11,double x22,double y22),注意要分两种情况考虑:有相交情况和没有相交情况。在有相交情况中,根据两个矩形其中的4个点的位置关系进行划分:
(x2>x11 &&y11>y2)||(x22>x1 && y1>y22)
剩下的与合并类似,属于判断方法。最后输出相交的矩形位置即可。
最后,在主函数中调用这4个函数以实现功能。
2代码清单
第一题:
package 实验3;
//定义一个Light类,描述灯这一类对象,给Light类增加成员变量的定义,
//描述有关灯这一类对象的属性“状态”,增加成员方法的定义“开灯”,描述有关灯这一类对象的操作,
//在main方法中把自定义好的类作为复合数据类型定义变量。在类Light的基础上,增加实例方法的定义,改变对象的实例变量的值,实现灯开或关的动作,改变灯的状态。
//定义一个带参数的构造方法,在构造方法中实现对象的初始化,另外需要顶一个无参数的构造函数。
public class Light_Test
{
public static void main(String[] args)
{
Light L1 = new Light(); //无参实例化
//Light L2 = new Light("关闭"); //有参构造实例化
String a = L1.getState();
System.out.println("初始状态为:");
L1.printlnfo(a);
L1.setState_On();
String b = L1.getState();
System.out.println("改变状态(开灯操作)后:");
L1.printlnfo(b);
L1.setState_Off();
String c = L1.getState();
System.out.println("再次改变(关灯操作)后:");
L1.printlnfo(c);
}
}
class Light
{
public String state;
public Light() //无参构造
{
this.state = "关闭";
}
public Light(String state) //有参构造
{
this.state = state;
}
public String getState()
{
return state;
}
public void setState_On()
{
this.state = "开启";
}
public void setState_Off()
{
this.state = "关闭";
}
public void printlnfo(String state)
{
System.out.println("灯的开关信息:"+ state);
System.out.println();
}
}
第二题:
package 实验3;
//定义一个类Rectangle,描述矩形对象以及矩形对象上的操作与运算,
//矩形的左上角坐标(x1,y1)和右下角坐标(x2,y2)可以确定一个矩形,4个坐标值可以定义成矩形的属性,
//在类Rectangle中定义不同的方法,
//实现矩形的如下运算:
//1.移动矩形;
//2.判断一个点是否在矩形内部;
//3.计算并返回与另一个矩形合并后的新矩形;
//4.计算并返回与另一个矩形相交后的新矩形,注意没有相交的情况。
//定义无参构造函数,默认左上角和右下角的坐标都是(0,0),实际是一个点。
//定义有4个参数的构造方法,分别代表左上角和右下角的坐标。
import java.util.Scanner;
public class Rectangle_Test
{
public static void main(String[] args)
{
double n1,n2,n3,n4,n5,n6,n7,n8;
Rectangle R1 = new Rectangle(); //无参构造方法@SuppressWarnings("resource")
Scanner reader = new Scanner(System.in);
System.out.println("请输入移动的目标坐标(4个输入,顺序x1,y1,x2,y2):");
n1 = reader.nextDouble();
n2 = reader.nextDouble();
n3 = reader.nextDouble();
n4 = reader.nextDouble();
R1.movePoint(n1,n2,n3,n4); //-1, 1, 1, -1
double x1 = R1.returnx1();
double y1 = R1.returnx2();// (x1,y1)为左上角
double x2 = R1.returnx2();
double y2 = R1.returny2();// (x2,y2)为右下角
System.out.println("请输入需要判断的点(2个输入,顺序为x,y):");
double x;
double y;
x = reader.nextDouble();
y = reader.nextDouble();
if(Rectangle.isInRectangle(x1, y1, x2, y2, x, y))
System.out.println("点(" + x + ","+ y + ")在矩形R1内部!");
else
System.out.println("点(" + x + ","+ y + ")不在矩形R1内部!");
System.out.println("请输入另一个矩形的坐标(4个输入,顺序为x1,y1,x2,y2):"); //-2, 2, 2, -2
n5 = reader.nextDouble();
n6 = reader.nextDouble();
n7 = reader.nextDouble();
n8 = reader.nextDouble();
Rectangle R2 = new Rectangle(n5,n6,n7,n8); //有4个参数构造方法
double x11 = R2.returnx1();
double y11 = R2.returnx2();// (x11,y11)为左上角
double x22 = R2.returnx2();
double y22 = R2.returny2();// (x22,y22)为右下角
Rectangle.combine(x1,y1,x2,y2,x11,y11,x22,y22); //计算并返回与另一个矩形合并后的新矩形;
Rectangle.intersects(x1,y1,x2,y2,x11,y11,x22,y22); //计算并返回与另一个矩形相交后的新矩形。
}
}
class Rectangle
{
public double x1;
public double y1;
public double x2;
public double y2;
Rectangle() //无参构造方法
{
this.x1 = 0;
this.y1 = 0;
this.x2 = 0;
this.y2 = 0; //左上角和右下角的坐标都是(0,0)
}
Rectangle(double x1,double y1,double x2,double y2) //有4个参数构造方法
{
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
public double returnx1() //以下依次返回x1 x2 y1 y2
{
return x1;
}
public double returny1()
{
return y1;
}
public double returnx2()
{
return x2;
}
public double returny2()
{
return y2;
}
public void movePoint(double x1,double y1,double x2,double y2)
{
this.x1 += x1;
this.y1 += y1;
this.x2 += x2;
this.y2 += y2;
System.out.println("移动后左上角坐标:(" + this.x1 + "," + this.y1 + ")");
System.out.println("移动后右下角坐标:(" + this.x2 + "," + this.y2 + ")");
}
//特殊情况:矩形平行于x轴和y轴
public static boolean isInRectangle(double x1,double y1,double x2,double y2,double x,double y)
{
if(x<=x1) return false;
if(x>=x2) return false;
if(y>=y1) return false;
if(y<=y2) return false;
return true;
}
public static void combine(double x1,double y1,double x2,double y2,double x11,double y11,double x22,double y22)
{
double x_1 = x1 < x11 ? x1 : x11; //小
double y_1 = y1 > y11 ? y1 : y11; //大
double x_2 = x2 > x22 ? x2 : x22; //大
double y_2 = y2 < y22 ? y2 : y22; //小
System.out.println("\n合并后左上角坐标:("+ x_1 + "," + y_1 + ") ;合并后右下角坐标(" + x_2 + "," + y_2 + ")");
}
public static void intersects(double x1,double y1,double x2,double y2,double x11,double y11,double x22,double y22)
{
if((x2>x11 && y11>y2)||(x22>x1 && y1>y22)) //两种情况
{
double x_1 = x1 > x11 ? x1 : x11; //大
double y_1 = y1 < y11 ? y1 : y11; //小
double x_2 = x2 < x22 ? x2 : x22; //小
double y_2 = y2 > y22 ? y2 : y22; //大
System.out.println("\n相交后左上角坐标:("+ x_1 + "," + y_1 + ") ;相交后右下角坐标(" + x_2 + "," + y_2 + ")");
}
else
System.out.println("没有相交!");
}
}
3运行结果
第一题:
第二题:
4.实验总结
1.什么是构造函数?
构造函数是一种特殊的函数,用来在对象实例化时初始化类的成员变量。构造函数主要的作用是完成对象的初始化工作。
1.构造函数的名字必须和类名一致,并且不能有返回值;
2.构造函数可以被重载,一个类可以有多个构造函数;
3.不能被继承,不能被重写;
4.当一个类没有定义构造函数时,编译器会默认生成一个无参的构造函数;
5.构造函数总是伴随着new操作一起调用,由系统调用。构造函数在对象实例化时自动被调用,只被调用一次。
举例:
public class Demo {
public static void main(String[] args)
{
//输出Hello World。new对象一建立,就会调用对应的构造函数Confun(),并执行其中的println语句。
Confun c1=new Confun();
}
}
class Confun{
Confun(){
//定义构造函数,输出Hello World
System.out.println("Hellow World");
}
}
2.程序中有多个类时如何确定源文件的名称?
源文件的命名规则是:
- 如果源文件中有多个类,只能有一个类是public类;如果有一个类是public类,那么源文件的名字必须与这个类的名字完全相同,扩展名是.java ;
- 如果源文件中有多个类,而源文件没有public类,那么 Java 程序源程序的主文件名可以是任意的,但推荐让 Java 源文件的名字和某个类的名字相同,这可以提供更好的可读性。并且扩展名是.java就可以了。
确定源文件的名称通常有如下建议:
1、一个 Java 源文件只定义一个类,不同的类使用不同的源文件定义。
2、让 Java 源文件的主文件名与该源文件中定义 的 public