“Java 语言程序设计实验 2023秋季”实验报告 面向接口编程

实验报告三 类和对象

一、实验目的及要求

  1. 实验目的:在面向抽象编程的基础上,掌握使用接口进行程序设计的核心思想是使用接口回调,明白接口也可以体现程序设计的“开-闭”原则,即对扩展开放,对修改关闭。

  2. 实验要求:深刻理解面向接口编程和“开-闭”原则,要求会定义接口变量,该接口变量存放了实现该接口的类的对象的引用,从而接口变量就可以回调类实现的接口方法。

  3. 上机实验内容:定义接口,声明若干个abstract方法;创建若干实现接口的类,在类中重写抽象方法、定义若干个参数为接口类型的方法,通过实现接口的类的对象回调类重写的接口方法,最后定义主类来实现相应功能,最后完成实验报告。

二、实验环境

  1. 硬件要求:计算机一台

  2. 软件要求:Windows操作系统,使用Java语言,集成开发环境不限,建议使用如Eclipse、MyEclipse或IntelliJ IDEA等。

三、实验内容

  1. 定义一个名为IAnimal的接口,并声明两个abstract方法,分别为eat()和sleep()。创建两个实现IAnimal接口的类,名为Dog和Cat,在这两个类中重写接口中的抽象方法。此外,定义一个名为ZooKeeper的类,包含一个IAnimal类型的成员变量,以及一个名为careForAnimal()的方法,该方法通过调用接口变量的eat()和sleep()方法来照顾动物。
  • 设计思路:

    (1)定义接口:首先定义一个名为IAnimal的接口,其中包含两个抽象方法eat()和sleep()。这个接口将为所有动物类提供一个公共的行为模板。

    (2)实现接口:创建两个类Dog和Cat,都实现IAnimal接口,并都需要实现eat()和sleep()方法。这两个类对IAnimal接口中定义的方法提供具体的实现。

    (3)创建ZooKeeper类:在ZooKeeper类中,包含一个IAnimal类型的成员变量,这样ZooKeeper就可以接管任何实现IAnimal接口的类的实例。ZooKeeper类中还包含一个名为careForAnimal()的方法,该方法通过调用IAnimal接口变量的eat()和sleep()方法来照顾动物。

    (4)实现“开-闭”原则:在上述设计中,如果想要添加一个新的动物类,只需要创建一个实现IAnimal接口的一个类,然后在ZooKeeper类中的IAnimal类型变量可以存放这个类的实例。ZooKeeper类无需做任何修改就可以照顾新的动物,这就体现“开-闭”原则。

  • 设计类图:

图片描述

                                         图1 题目一类图
  • 实验步骤:

    (1)定义IAnimal接口,包括eat()和sleep()两个抽象方法。

    (2)创建Dog类和Cat类,这两个类都实现IAnimal接口,并重写eat()和sleep()方法。

    (3)设计并实现ZooKeeper类,包含一个IAnimal类型的成员变量,以及一个名为careForAnimal()的方法,该方法通过调用接口变量的eat()和sleep()方法来照顾动物。

    (4)在主方法中,创建Dog类和Cat类的实例,并将这些实例传递给ZooKeeper类的对象,通过调用ZooKeeper对象的careForAnimal()方法来照顾这些动物。

    (5)执行程序,观察并分析结果。

  1. 定义一个名为IDriveable的接口,并声明两个abstract方法,分别为start()和stop()。创建两个实现IDriveable接口的类,分别为Car和Bike,在这两个类中重写接口中的抽象方法。此外,在Car类中,再定义一个参数为IDriveable类型的方法,代表这辆车可以拖拉其他可驾驶的物体。最后在主类中实例化Car对象,通过接口变量调用拖拉方法。
  • 设计思路:

    (1)定义接口:首先定义一个名为IDriveable的接口,其中包含两个抽象方法start()和stop()。这个接口将为所有可驾驶物体提供一个公共的行为模板。

    (2)实现接口:接着创建两个类Car和Bike,它们都实现IDriveable接口,这意味着它们都要实现start()和stop()方法。这两个类对IDriveable接口中定义的方法提供具体的实现。

    (3)接口回调:在Car类中,定义一个参数为IDriveable类型的方法tow(),表示这辆车可以拖拉其他可驾驶的物体。在这个方法中,调用IDriveable接口的start()和stop()方法,实现接口回调。

  • 设计类图:

图片描述

                                     图2 题目二类图
  • 实验步骤:

    (1)定义IDriveable接口,包括start()和stop()两个抽象方法。

    (2)创建Car类和Bike类,这两个类都要实现IDriveable接口,并重写start()和stop()方法。

    (3)在Car类中,定义一个参数为IDriveable类型的tow()方法,表示这辆车可以拖拉其他可驾驶的物体。

    (4)在主方法中,创建Car类和Bike类的实例,并将Bike类的实例传递给Car类的对象,通过调用Car对象的tow()方法实现拖拉功能。

    (5)执行程序,观察并分析结果。在结果中,应该能看到,当Car对象调用tow()方法时,实际上是通过接口回调,调用Bike对象的start()和stop()方法。

  1. 定义一个名为IStrategy的接口,并在此接口中声明一个abstract方法,execute()。创建两个实现IStrategy接口的类,分别为ConcreteStrategyA和ConcreteStrategyB,在这两个类中重写execute()方法。定义一个名为Context的类,包含一个IStrategy类型的成员变量和一个名为executeStrategy()的方法,该方法通过接口变量调用execute()方法。
  • 设计思路:

    (1)定义接口:首先定义一个名为IStrategy的接口,其中包含一个抽象方法execute()。这个接口将为所有策略提供一个公共的行为模板。

    (2)实现接口:然后创建两个类ConcreteStrategyA和ConcreteStrategyB,它们都实现IStrategy接口,这意味着它们都要实现execute()方法。这两个类对IStrategy接口中定义的方法提供具体的实现。

    (3)创建Context类:在Context类中,包含一个IStrategy类型的成员变量,这样Context就可以接管任何实现IStrategy接口的类的实例。Context类中还包含一个名为executeStrategy()的方法,该方法通过调用IStrategy接口变量的execute()方法来执行策略。

    (4)实现“开-闭”原则:在上述设计中,如果想要添加一个新的策略类,例如ConcreteStrategyC,只需要创建一个实现IStrategy接口的ConcreteStrategyC类,然后在Context类中的IStrategy类型变量可以存放ConcreteStrategyC类的实例。Context类无需做任何修改就可以执行新的策略,这就体现“开-闭”原则。

  • 设计类图:

图片描述

                                     图3  题目三类图
  • 实验步骤:

    (1)定义IStrategy接口,包括execute()抽象方法。

    (2)创建ConcreteStrategyA类和ConcreteStrategyB类,这两个类都要实现IStrategy接口,并重写execute()方法。

    (3)设计并实现Context类,包含一个IStrategy类型的成员变量,以及一个名为executeStrategy()的方法,该方法通过调用接口变量的execute()方法来执行策略。

    (4)在主方法中,创建ConcreteStrategyA类和ConcreteStrategyB类的实例,并将这些实例传递给Context类的对象,通过调用Context对象的executeStrategy()方法来执行策略。

    (5)执行程序,观察并分析结果。

  1. 定义一个函数接口IGreeting,它声明一个接受String参数并返回void的方法sayHello。接下来,创建一个名为Greeting的类,包含一个接受IGreeting类型参数的方法greet,这个方法通过函数接口变量调用sayHello方法。在主类中,使用Lambda表达式创建一个IGreeting对象,并将其传递给Greeting类的greet方法。这个Lambda表达式接受一个字符串参数,并打印一条欢迎消息。
  • 设计思路:

    (1)定义函数接口:首先定义一个名为IGreeting的函数接口,其中包含一个接受String参数并返回void的方法sayHello。

    (2)创建类:然后创建一个名为Greeting的类,它包含一个接受IGreeting类型参数的方法greet。在这个方法中,通过函数接口变量调用sayHello方法。这样就可以通过传入不同的IGreeting实例来改变greet方法的行为。

    (3)使用Lambda表达式:在主类中,使用Lambda表达式创建一个IGreeting对象,然后将其传递给Greeting类的greet方法。这个Lambda表达式接受一个字符串参数,并打印一条欢迎消息。

  • 设计类图:

图片描述

                                     图4  题目四类图
  • 实验步骤:

    (1)定义函数接口IGreeting,包括接受String参数并返回void的sayHello方法。

    (2)创建Greeting类,包含一个接受IGreeting类型参数的方法greet。在这个方法中,通过函数接口变量调用sayHello方法。

    (3)在主类中,使用Lambda表达式创建一个IGreeting对象,然后将其传递给Greeting类的greet方法。

    (4)执行程序,观察并分析结果。在结果中,当主类调用Greeting类的greet方法时,实际上是通过函数接口和Lambda表达式,打印出一条欢迎消息。

##四、实验结果与分析

  1. 题目一

实验结果:

图片描述

                                     图5 题目一输出结果

实验结果分析:

实验通过定义IAnimal接口及Dog、Cat两个实现类来展示接口回调。ZooKeeper类的careForAnimal()方法通过IAnimal接口来调用具体实现类的eat()和sleep()方法,实现对动物的照顾。这体现“开-闭”原则:即添加新的动物类(实现IAnimal接口)时,ZooKeeper类无需修改即可照顾新动物。经检验,实验结果符合预期。

  1. 题目二
  • 实验结果:

图片描述

                                     图6  题目二输出结果
  • 实验结果分析:

本实验创建了一个简单的驾驶模型,其中包括一个IDriveable接口、两个实现这个接口的类(Car和Bike)以及一个主类。在此方法中,它首先打印出正在拖拉的信息,然后调用被拖物体的start和stop方法,表示启动和停止被拖拉的物体。在主类中,创建一个Car对象和一个Bike对象,然后让汽车启动、拖拉自行车,最后停止汽车。经检验,实验结果符合预期。

  1. 题目三
  • 实验结果:

图片描述

                                     图7 题目三输出结果
  • 实验结果分析:

在本实验中,在主类中,创建 ConcreteStrategyA 和 ConcreteStrategyB 的对象,并创建一个 Context 对象,初始策略为 ConcreteStrategyA。然后调用 executeStrategy 方法执行策略,接着更改策略为 ConcreteStrategyB,再次调用 executeStrategy 方法执行策略。经检验,实验结果符合预期。

  1. 题目四
  • 实验结果:

图片描述

                                     图8  题目四输出结果
  • 实验结果分析:

本实验成功地通过Lambda表达式实现匿名函数,并通过函数接口传递给 greet 方法。经检验,实验结果符合预期。

  1. 实验中遇到的问题:

    (1)定义接口时没有正确声明抽象方法,在定义IAnimal接口时,eat()和sleep()方法没有加abstract关键字。

    (2)实现接口类没有正确重写抽象方法,Dog类和Cat类实现IAnimal接口后,没有重写eat()和sleep()方法。

    (3)接口类型变量无法调用具体方法,通过IAnimal接口变量无法调用eat()和sleep()方法。

    (4)类定义错误,没有实现接口,定义Dog类时没有添加implements IAnimal。

  2. 问题解决的方法:

    (1)正确定义接口时,接口方法需要加abstract关键字。

    (2)类实现接口后需要重写接口中的所有抽象方法,否则该类的对象无法被当成接口使用。

    (3)由于接口变量保存的是实现类对象的引用,但其类型是接口类型,所以无法直接调用实现类中的具体方法。需要强制类型转换为实现类后再调用。

    (4)当类需要实现某个接口时,在类定义时需要使用implements关键字明确指定实现的接口,否则该类不会被视为实现了该接口。

##五、附源程序

1.题目1:

Main.java

// 定义一个动物接口,包含吃和睡觉的操作
interface IAnimal {
    void eat();
    void sleep();
}
// 实现Animal接口的Dog类
class Dog implements IAnimal {
    // 重写eat方法
    public void eat() {
        System.out.println("狗正在吃饭..."); // 打印狗正在吃饭的信息
    }
    // 重写sleep方法
    public void sleep() {
        System.out.println("狗正在睡觉..."); // 打印狗正在睡觉的信息
    }
}
// 实现IAnimal接口的Cat类
class Cat implements IAnimal {
    // 重写eat方法
    public void eat() {
        System.out.println("猫正在吃饭..."); // 打印猫正在吃饭的信息
    }
    // 重写sleep方法
    public void sleep() {
        System.out.println("猫正在睡觉..."); // 打印猫正在睡觉的信息
    }
}
// 定义一个动物园管理员类,用于照顾动物
class ZooKeeper {
    private IAnimal animal; // 定义一个Animal类型的私有变量
    // ZooKeeper的构造方法,需要传入一个Animal类型的变量
    public ZooKeeper(IAnimal animal) {
        this.animal = animal; // 将传入的animal赋值给类的animal变量
    }
    // 照顾动物的方法,包括动物的吃和睡觉的操作
    public void careForAnimal() {
        animal.eat(); // 动物吃东西
        animal.sleep(); // 动物睡觉
    }
}
public class Main {
    public static void main(String[] args) {
        IAnimal dog = new Dog(); // 创建一个Dog类型的动物
        IAnimal cat = new Cat(); // 创建一个Cat类型的动物
        ZooKeeper zooKeeper = new ZooKeeper(dog); // 创建一个ZooKeeper对象,照顾的动物为dog
        System.out.println("动物园管理员正在照顾狗:");
        zooKeeper.careForAnimal(); // 动物园管理员照顾狗
        zooKeeper = new ZooKeeper(cat); // 创建一个新的ZooKeeper对象,照顾的动物为cat
        System.out.println("\n动物园管理员正在照顾猫:");
        zooKeeper.careForAnimal(); // 动物园管理员照顾猫
    }
}
  1. 题目2:

Main.java

// 定义一个可驾驶的接口,包含启动和停止的操作
interface IDriveable {
  void start();
  void stop();
}
// 实现IDriveable接口的Car类
class Car implements IDriveable {
  // 重写start方法
  public void start() {
    System.out.println("汽车正在启动..."); // 打印汽车正在启动的信息
  }
  // 重写stop方法
  public void stop() {
    System.out.println("汽车正在停止..."); // 打印汽车正在停止的信息
  }
  // 定义一个参数为IDriveable类型的方法,表示汽车可以拖着其他可以驾驶的物体
  public void tow(IDriveable driveable) {
    System.out.println("汽车正在拖拉另一个可驾驶的物体..."); // 打印汽车正在拖拉的信息
    driveable.start(); // 启动被拖拉的物体
    driveable.stop(); // 停止被拖拉的物体
  }
}
// 实现IDriveable接口的Bike类
class Bike implements IDriveable {
  // 重写start方法
  public void start() {
    System.out.println("自行车正在启动..."); // 打印自行车正在启动的信息
  }
  // 重写stop方法
  public void stop() {
    System.out.println("自行车正在停止..."); // 打印自行车正在停止的信息
  }
}
public class Main {
  public static void main(String[] args) {
    Car car = new Car(); // 创建一个Car对象
    Bike bike = new Bike(); // 创建一个Bike对象
    car.start(); // 启动汽车
    car.tow(bike); // 汽车拖拉自行车
    car.stop(); // 停止汽车
  }
}
  1. 题目3:

Main.java

// 定义一个策略接口,包含一个执行方法
interface IStrategy {
  void execute();
}
// 实现IStrategy接口的ConcreteStrategyA类,代表策略A
class ConcreteStrategyA implements IStrategy {
  // 重写execute方法
  public void execute() {
    System.out.println("执行策略A..."); // 打印执行策略A的信息
  }
}
// 实现IStrategy接口的ConcreteStrategyB类,代表策略B
class ConcreteStrategyB implements IStrategy {
  // 重写execute方法
  public void execute() {
    System.out.println("执行策略B..."); // 打印执行策略B的信息
  }
}
// 定义一个上下文类,用于使用策略
class Context {
  private IStrategy strategy; // 定义一个IStrategy类型的私有变量
  // Context的构造方法
  public Context(IStrategy strategy) {
    this.strategy = strategy; // 将传入的strategy赋值给类的strategy变量
  }
  // 设置策略的方法
  public void setStrategy(IStrategy strategy) {
    this.strategy = strategy; // 将传入的strategy赋值给类的strategy变量
  }
  // 执行策略的方法
  public void executeStrategy() {
    strategy.execute(); // 调用传入策略的execute方法
  }
}
public class Main {
  public static void main(String[] args) {
    IStrategy strategyA = new ConcreteStrategyA(); // 创建一个ConcreteStrategyA对象
    IStrategy strategyB = new ConcreteStrategyB(); // 创建一个ConcreteStrategyB对象
    Context context = new Context(strategyA); // 创建一个Context对象,初始策略为strategyA
    context.executeStrategy(); // 执行策略
    context.setStrategy(strategyB); // 更改策略为strategyB
    context.executeStrategy(); // 执行策略
  }
}
  1. 题目4:

Main.java

// 定义一个函数接口,有一个String类型参数的方法
interface IGreeting {
  void sayHello(String name);
}
// Greeting类,有一个greet方法,这个方法接受一个IGreeting接口和一个String类型的参数
class Greeting {
  public void greet(IGreeting greeting, String name) {
    greeting.sayHello(name); // 调用sayHello方法
  }
}
public class Main {
  public static void main(String[] args) {
    Greeting greeting = new Greeting(); // 创建一个Greeting对象
    // 使用Lambda表达式创建一个IGreeting对象
    IGreeting helloGreeting = name -> System.out.println("Hello, " + name + "!");
    // 调用greet方法
    greeting.greet(helloGreeting, "World");
  }
}
  • 15
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java语言程序设计编程练习是指针对Java语言进行编程训练和实践的活动。通过这种练习,可以加深对Java语言的理解,并提升编程能力。 在Java语言程序设计编程练习中,可以选择不同的题目或项目进行实践。这些题目或项目可以根据难度分为初级、中级和高级,以满足不同程度的学习和训练需求。 在练习过程中,可以通过编写各种类型的程序,例如控制台应用程序、图形用户界面(GUI)应用程序和Web应用程序等。这些程序可以涉及到不同的主题和功能,如算法实现、数据结构、数据库连接、网络通信等等。 通过进行Java语言程序设计编程练习,可以不断提高解决问题的能力和编码技巧。在每个练习中,可以通过分析问题、设计程序结构、编写代码和调试等步骤,逐渐提高在使用Java语言进行程序设计开发方面的能力。 同时,参与Java语言程序设计编程练习还可以为接下来的工作或学习提供更好的准备。无论是从事软件开发工作,还是进行进一步的学术研究,Java语言程序设计编程练习都可以帮助培养良好的编程思维和解决问题的能力。 综上所述,Java语言程序设计编程练习是一种有益的学习和提升编程能力的活动。通过不断的练习和实践,可以不断提高编程技巧和解决问题的能力,为后续的工作和学习打下坚实的基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值