admin 管理员组文章数量: 887021
2024年1月17日发(作者:快速排序的全部代码)
一、实验目的
1. 深入理解类的继承的基本概念及实现。
2. 了解Object及对Object类的主要方法equals进行重写。
3. 掌握super关键字的作用。
4. 掌握抽象类与接口的基本概念及实际应用
5. 掌握对象多态性的作用。
6. 掌握接口的基本概念及实际应用。
7. 掌握接口回调的概念及运行机制。
二、实验内容及步骤
1、重写Object类的equals方法
任务一:使用继承自Object类的equals方法进行Person对象的比较操作。
(1)源代码如下:
class Person{
private String name;
private int age;
public Person(String name,int age){
= name;
= age;
}
//getter与setter方法略。
public String toString(){
return "姓名:"++";年龄:"+;
}
}
public class PersonDemo{
public static void main(String args[]){
Person person1 = new Person(“李兴华”,30);
Person person2 = new Person(“李兴华”,30);
n((person2)?"是同一个人。":"不是同一个人。");
}
}
(2)编译并运行应用程序。
运行结果:
(3)实验报告
将运行结果写在实验报告中。
思考:应用程序中person1对象调用的equals方法是从哪个类继承的,请查看源代码,说明此equals方法的作用,即比较的内容。
答:person1对象调用的equals方法是从Object类继承的。
此equals方法的目的是通过boolean判断两对象内存地址是否相同。
任务二:修改上述源代码Person类,使PersonDemo应用程序执行结果为“同一个人”。
提示:equals方法的原型是:public boolean equals(Object obj){}
源代码:
public boolean equals(Object obj){
if(obj==null||!(obj instanceof Person)) {
return false;
}
if(((Person) obj).name==&&((Person) obj).age==) {
return true;
}
return false;
}
运行结果:
2、对象的上转型对象
任务一:对象的上转型对象接收任意子类类型的对象
(1)使用Object接收一切的引用类型对象。
源代码:
class A{
public String getInfo(){
return “Hello World!!!”;
}
}
public class ADemo{
public static void main(String args[]){
Object obj = new A();
n(o());
n(ng());
A a = (A)obj;
n(o());
n(ng());
}
}
(2)编译并运行程序。
运行结果:
(3)实验报告
将运行结果写在实验报告中。
如果程序编译为通过,或运行时有错误提示,请说明原因,并将错误改正。
答:错误:The method getInfo() is undefined for the type Object 方法getInfo()没有被定义,需要add cast to Obj,改为n(((A) obj).getInfo());即可。
任务二:上转型实现多态性
(1) 实例学习
源代码:
package renwu3;
class A {
public void fun1(){
n("A-->public void fun1(){}");
}
public void fun2() {
1();
}
};
不使用上转型对象实现多态性源代码如下:
package renwu3;
class B extends A {
public void fun1() {
n("B-->public void fun1(){}");
}
public void fun3() {
n("B-->public void fun3(){}");
}
};
package renwu3;
class C extends A{
public void fun1() {
n("C-->public void fun1(){}");
}
public void fun5() {
n("C-->public void fun3(){}");
}
};
package renwu3;
public class PolDemo4 {
}
public static void main(String[] args) {
// TODO Auto-generated method stub
fun(new B());//传递B类实例
fun(new C());//传递C类实例
}
public static void fun(B b) {
1();//统一调用覆写父类的fun1()方法
}
public static void fun(C c) {
1();
}
运行结果:
以上程序虽然实现了基本的要求,但是可以发现:如果按照以上的方式完成程序,则当产生一个A类的子类时,fun()方法就要重载一次,这样如果功能扩充,则必须要修改类本身,那么如果使用对象多态性完成呢?
使用上转型对象实现多态性:
源代码:
package renwu1;
class A {
public void fun1(){
n("a-->public void fun1(){}");
}
public void fun2() {
1();
}
};
package renwu1;
class B extends A {
public void fun1() {
n("B-->public void fun1(){}");
}
public void fun3() {
n("B-->public void fun3(){}");
}
};
package renwu1;
class C extends A {
public void fun1() {
n("C-->public void fun1(){}");
}
public void fun5() {
n("C-->public void fun3(){}");
}
}
package renwu1;
public class PolDemo05 {
public static void main(String[] args) {
// TODO Auto-generated method stub
fun(new B());//传递B类实例,产生向上转型
fun(new C());//传递C类实例,产生向上转型
}
public static void fun(A a) { //接收父类对象
1();
}
}
运行结果:
(2)阅读上述两个源代码,深刻理解使用上转型对象实现多态性机制。
答:上转型:是子类对象由父类引用。想要上转型的前提必须是由继承关系的两个类,在调用方法的时候,上转型对象只能调用父类中有的方法,如果调用子类方法则会报错。
3、抽象类与上转型对象练习
任务一:通过对上述实验内容的实践与学习,根据要求填写代码。
(1)要求:
有一家公司,有不同类型的员工,包括按年领取薪水,按月领取薪水,按周领取薪水,计算该公司一年需支付的薪水总额
有一个abstract类,类名为Employee;
该类有一个abstract方法:
public abstract double earnings( );;
Employee的子类有YearWorker、MontthWorker和WeekWorker。
YearWorker对象按年领取薪水,MonthWorker按月领取薪水,WeekWorker按周领取薪水。
子类必须实现父类的earnings()方法,返回各自领取薪水数。
有一个Company类,该类用employee数组作为成员,employee数组的
单元可以是YearWorker对象的上转型对象、MonthWorker对象的上转型对象或WeekWorker对象的上转型对象。
程序能输出Company对象一年需要支付的薪水总额。
(2)代码模板
源代码:
package renwu2;
public class Company {
Employee[] employee;
double salaries=0;
Company(Employee[] employee){
ee=employee;
}
public double salariesPay(){
salaries=0;
for(int i=0;i<;i++){
salaries=salaries+employee[i].earnings();
}
return salaries;
}
}
package renwu2;
abstract class Employee {
public abstract double earnings( );
}
package renwu2;
public class WeekWorker extends Employee{
public double earnings(){
return 52*1000;
}
}
package renwu2;
public class MonthWorker extends Employee{
public double earnings(){
return 12*5000;
}
}
package renwu2;
public class YearWorker extends Employee {
public double earnings(){
return 120000;
}
}
package renwu2;
public class HardWork {
public static void main(String[] args){
Employee[] employee=new Employee[20]; //公司有20名职员
for(int i=0;i<;i++){
if(i%3==0)
employee[i]=new WeekWorker();
else if(i%3==1)
employee[i]=new MonthWorker();
else if(i%3==2)
}
}
employee[i]=new YearWorker();
}
Company company=new Company(employee);
n("公司年工资总额:"+esPay()+"元");
运行结果:
(3)实验报告
将代码1-4写在实验报告中。
在Employee类的子类中合适位置使用super,再运行程序。根据查看的结果,验证在子类中是否可以调用抽象类父类的构造方法,即抽象类是否有构造方法?
答:子类可以调用抽象类父类的构造方法。
4、接口案例学习
任务一:学习下面实例,定义一个抽象的汽车类car,再将汽油车设计为接口。该程序代码如下:
import ; //汽车抽象类
public abstract class Car
{
//公用数据字段声明区
public Color color; //车辆颜色
public int gearNum; //排档数
public String tiretype; //轮胎型号
public float engine; //引擎排气量
//公用抽象方法声明区
public abstract void shiftgear(); //换档
public abstract void brake(); //煞车
public abstract void aircon(); //开冷气
public abstract void headlight(); //开大灯
}
public interface Gasoline //汽油车接口
{
public static final String FUEL="gasoline(汽油)";//定义一个最终字段
public void refuel(); //声明一个方法
}
源代码:
package renwu3;
public class Gcar extends Car {
static int gearNum=5;//声明gearNum为类栏
public Gcar() {
tiretype="BridgeStone185ST";//轮胎型号
engine=1598.5f;//排气量
}
public static void main(String args[]) {
Gcar gcar=new Gcar();//产生实例
ent();
ear();
();
}
public void equipment() {//轿车的配置
n("轿车颜色:"+color);
n("轿车排挡数:"+gearNum);
n("轿车轮胎型号:"+tiretype);
n("轿车排气量:"+engine);
}
public void shiftgear() {
n("轿车换挡方式:自排"+gearNum+"文件");
}//换挡
public void brake() {
n("水压式刹车系统");
}//刹车
public void aircon() {};//开冷气
public void headlight() {};//开大灯
}
任务二:(1)根据以上代码,定义你自己的车,该车继承自汽车类car并实现汽油车接口。
自己的车属性为:档位为5个档,轮胎型号是BridgeStone185ST,排气量为1598.5。
自己的车的新增的方法有:equipment():输出轿车颜色、轿车排档数、轿车轮胎型号、轿车排气量和轿车燃料。
源代码:
package renwu3;
import ; //汽车抽象类
public class MyCar extends Gcar{
private Color color;
public MyCar() {
color=;//设置汽车颜色
}
public static void main(String args[]) {
MyCar mycar=new MyCar();
ent();
ear();
();
}
public void equipment() {
n("我的车排挡数:"+m);
n("我的车颜色:"+);
n("我的车轮胎型号:"+pe);
n("我的车引擎排气量:"+);
}
public void shiftgear() {//换挡-覆盖的新方式
n("我的车换挡方式:自排"+m+"档");
}
@Override
public void brake() {
// TODO Auto-generated method stub
}
@Override
public void aircon() {
// TODO Auto-generated method stub
}
@Override
public void headlight() {
// TODO Auto-generated method stub
}
}
(2)实验报告
将任务二的代码写在实验报告中。
编写应用程序测试实现类。
运行结果:
(2) 注意:在实现接口时,要实现所有接口中定义的所有方法,方法的实现可以具有具体的实现内容,也可以是抽象的方法,即只有方法名或参数,没有变量、没有具体操作语句,只有一对大括号{}的空方法。
5、接口的回调
任务一:有一家商店销售电视、计算机和手机,计算该商店的年销售总额
(1) 要求:
有一个ComputeTotalSales接口,该接口中有一个方法:
public double totalSalesByYear();
有三个实现该接口的类:Television,Computer和Mobile。这三个类通过实现接口
computeTotalSales给出自己的年销售额。
有一个Shop类,该类用computeTotalSales数组作为成员,computeTotalSales数
组的单元可以存放Television对象的引用或Mobile对象的引用。
编写应用程序输出Shop对象的年销售额。
(2)代码模板
源代码:
interface ComputeTotalSales
{
public double totalSalesByYear( );
}
class Television implements ComputeTotalSales
{
public double totalSalesByYear() {// 实现totalSalesByYear( )方法
return 60000;}
class Compute implements ComputeTotalSales
{
public double totalSalesByYear() { // 实现totalSalesByYear( )方法
{
public double totalSalesByYear() {// 实现totalSalesByYear( )方法
{
ComputeTotalSales[ ] goods;
double totalSales=0;
Shop(ComputeTotalSales[ ] goods)
{
=goods;
}
public double giveTotalSales( )
{
totalSales=0;
for (int i=0; i<; i++) {// 计算totalSales
totalSales = totalSales + goods[i].totalSalesByYear();
} return totalSales;
}
}
public class HappySale
{
public static void main(String args[ ])
{
ComputeTotalSales[ ] goods=new ComputeTotalSales[3];
for(int i=0;i<;i++)
{
if(i%3==0)
goods[i]=new Television( );
else if(i%3==1)
goods[i]=new Computer( );
else if(i%3==2)
goods[i]=new Mobile( );
}
Shop shop=new Shop(goods);
return 50000;}
class Shop
return 10000;}
class Mobile implements ComputeTotalSales
n("商店年销售额:"+talSales( ) );
}
}
运行结果:
*任务二:利用接口回调和反射独立编程。
(1)内容及要求
假定现有两种工具:Car 和Plane,其中Car 的平均速度运算公式为:a*b/c;Plane的平均速度运算公式为:a+b+c,三个参数的具体值在程序运行时用户录入。
编写ComputeTime类,通过该类计算用户指定的交通工具运行1000公里所需的时间。参数的具体值在程序运行时用户录入。
其运行过程如下,从命令行输入ComputeTime的四个参数,第一个是交通工具的类型,第二、三、四个参数分别时整数A、B、C,举例如下:
计算Plane的时间:"java ComputeTime Plane 20 30 40"。
计算Car的时间:"java ComputeTime Car 23 34 45"。
编程要求:
在未来如果增加第3种交通工具的时候,只需要编写新的交通工具的程序。如第3种交通工具为Ship,则只需要编写,运行时输入:"java ComputeTime Ship 22 33
44"。
充分利用接口及接口回调的技术。
提示:实例化一个对象的另外一种办法:e(str).newInstance();
例如需要实例化一个Plane对象:Plane plane =
(Plane)e("Plane").newInstance()
(2)实验报告
源代码:
package renwu5;
import ;
import .*;
public class ComputeTime {
public static void main(String args[]) {
n("交通工具:"+args[0]);
n("参数a:"+args[1]);
n("参数b:"+args[2]);
n("参数c:"+args[3]);
double a=ouble(args[1]);
double b=ouble(args[2]);
double c=ouble(args[3]);
double v,t;
try {
Common
d=(Common)e("e."+args[0]).newInstance();
v=er(a,b,c);
t=1000/v;
n("平均速度:"+v+"km/h");
n("运行时间:"+t+"小时");
}
catch(Exception e) {
n("class not found");
}
}
}
package renwu5;
import ;
import .*;
public class Plane implements Common{
public double runTimer(double a,double b,double c) {
return(a+b+c);
}
}
package renwu5;
import ;
public class Car implements Common{
public double runTimer(double a,double b,double c) {
return(a*b/c);
}
}
package ;
public interface Common {
double runTimer(double a,double b,double c);
}
三、实验结果及分析
与定义类的class不同,接口定义时需要使用interface关键字。
定义接口所在的仍为.java文件,虽然声明时使用的为interface关键字的编译后仍然会产生.class文件。这点可以将接口看做是一种只包含了功能声明的特殊类。接口中的方法全是抽象方法,直接new接口来调用方法没有意义,Java也不允许这样干。类与接口的关系为实现关系,即类实现接口。实现的动作类似继承,只是关键字不同,实现使用implements。其他类(实现类)实现接口后,就相当于声明:”我应该具备这个接口中的功能”。实现类仍然需要重写方法以实现具体的功能。
版权声明:本文标题:Java语言实验5 多态性与接口 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1705421616h484113.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论