北航软工: 面向对象程序设计(2024) Lab 3

Lab 3

Lab 3 Problem Set

题面附件代码见https://github.com/charcai/BUAA-OOP-2024/tree/main/Lab03/Lab3-Code

解答代码见https://github.com/charcai/BUAA-OOP-2024/tree/main/Lab03/

Question1: Package

浏览 Code 目录下的 Question01 目录,不允许变更目录结构和文件位置,只允许在文件中添加 packageimport 语句,使根目录下 buildtest 文件中的指令可以无报错顺利执行。

buildtest 为脚本文件,直接在 IDE 或文本编辑器中打开即可看到其中的指令。

PS.不要轻易相信IDEA自动加的,报红的是可以通过编译运行的

你可以把 Question01 目录复制到解答的压缩包中,或者在解答报告中直接以文字或截图说明你的改动。

Question2:方法重写

阅读 Code 目录下的 Question02 目录,根据你对方法重写规则的理解,回答下列问题并改正代码错误

  1. Worker.java1 号注释处正确吗,如果不正确应该怎么改正,为什么?
  2. 如果 Worker.javaeat() 方法的修饰符改为 private,可以通过编译吗,为什么?
  3. Teacher.java2 号注释处正确吗,如果不正确应该怎么改正,为什么?
  4. Teacher.java3 号注释处正确吗,如果不正确应该怎么改正,为什么?
  5. 属性、静态方法、非静态方法,哪些可以覆盖(重写 / override),哪些可以隐藏?

你可以把 Question02 目录复制到解答的压缩包中,或者在解答报告中直接以文字或截图说明你的改动。

Question3: super VS this

完成下面表格,复制或截图在解答报告中

区别点thissuper
引用(代表什么)
使用方式
调用构造方法(调用谁的构造方法,放在第几条语句)
查找范围(查找顺序)

Question4: final

在实验报告中回答下列问题

  1. final 修饰的类可以被继承吗?可以继承其它类吗?
  2. final 修饰的方法可以被重写吗?
  3. final 修饰的变量相当于什么?
  4. final 修饰的引用类型变量可以改变其引用地址吗?可以改变对象的内部属性的值吗?

Question5: 权限

阅读 Code 目录下的 Question05 目录,根据你对访问权限的理解。将文件中所有无法通过编译的语句注释掉。

你遇到的问题可能会集中在 protected 和默认访问权限。 从这次实验和上一次实验,可以引申出两个问题,你需要在解答中说出你的想法。

  • Lab 2 中的单例模式,或者说所有构造方法都是 private 时,可能有子类吗?
  • final 类可以视为所有构造方法都是 private 的类吗?

你可以把 Question05 目录复制到解答的压缩包中,或者在解答报告中直接以文字或截图说明你的改动。

Question6: Shape

阅读下面的二维形状类 Shape

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
public abstract class Shape {
    protected double a;
    protected double b;

    public Shape() { this(0.0, 0.0); }
    public Shape(double a, double b) {
        this.a = a;
        this.b = b;
    }

    /** calcArea
    * 计算形状的面积
    * @return 面积
    */
    abstract public double calcArea();

    /* 其他必要的方法,比如 getter 和 setter */
}

你的任务是:

  • 编写 Rectangle 类,ab 分别代表矩形两条边的长度(长和宽);
  • 编写 Rhombus 类,ab 分别代表两条菱形对角线的长度;
  • 编写 Ellipse 类,ab 分别代表椭圆两个半轴(半长轴和半短轴)的长度;
  • 编写一个测试类,构造子类对象并测试。

注意:

  • 上述三个类都继承自 Shape 类,都必须要 override 方法 calcArea
  • ab 都不能是负数,当通过 constructor 或者 setter 设定为负数时,将对应的值置为 0.0,或 throw 异常;
  • ab 的大小关系没有任何约束,没有 a 必须不小于 b 的说法。

题外话

我们知道属性不设置为 public 是为了保护数据,如果 abShape 中的访问权限被设置为 private,在不添加新的属性的情况下,子类想要实现自己的 calcArea()该怎么办?在解答中写出你的思考。

Question7: 车车

定义一个 Vehicle 类,在其中声明一个属性代表这个交通工具有多少个轮子,提供对这个属性的 setter。提供轮子类、引擎类。创建几个 Vehicle 的导出类:MotorbikeCarTank。自由发挥,在测试类中构造这几种交通工具,并测试功能。

其中 Motorbike 类需增加两个属性:driverpassenger 表示司机和乘客。增加你觉得合适的方法。

定义一个 Person 类,加入你觉得合适的属性和方法,生成 brothersister 两个对象,结合 Motorbike 试图实现以下场景:

  • 生成三个对象(Motorbike 实例 motorbikePerson 实例 brothersister
  • 设置 motorbike 的司机与乘客为 brothersister
  • 打印 motorbike 的信息(尽可能详细)
  • 调用 sistersay() 方法,输出“不像我,我只会心疼 giegie~”

备注:这道题目绝不是 2321 同学们的助教出的。

Lab 3 Assignment

Question1

代码打包为文件夹,见 ./Question01/ 目录。

Question2

修改后的文件见./Question02/

  1. Worker.java1 号注释处正确吗,如果不正确应该怎么改正,为什么?

    不正确。 可以将 @Override 行删除。

    Worker.eat()People.eat() 所传递的参数不同,构成 Overload 而非 Override,故签名不正确。

  2. 如果 Worker.javaeat() 方法的修饰符改为 private,可以通过编译吗,为什么?

    不可以。Java 中,子类 Override 的方法不能比父类中被 Override 的方法有更低的访问级别。

  3. Teacher.java的 2 号注释处正确吗,如果不正确应该怎么改正,为什么?

    不正确。Java 中,子类 Override 的方法应与父类中被 Override 的方法有相同的返回类型。本代码中,Teacher.work() 返回类型是People,而 Worker.work() 返回类型是 Worker

    可将 Teacher.work() 的返回类型改为 Worker, 将返回值改为 return new Worker();

  4. Teacher.java3 号注释处正确吗,如果不正确应该怎么改正,为什么?

    不正确。 问题同上,在 Java 中,子类 Override 的方法应与父类中被 Override 的方法有相同的返回类型。

    可将 Worker.salary() 的返回类型改为 long

  5. 属性、静态方法、非静态方法,哪些可以覆盖(重写 / override),哪些可以隐藏?

    • 属性不能被覆盖,可以被隐藏。
    • 静态方法不能被覆盖,可以被隐藏。
    • 非静态方法可以被覆盖,不能被隐藏。

Question3

区别点thissuper
引用当前对象的引用父类对象的引用
使用方式用于访问当前对象的成员变量和方法用于访问当前对象的成员变量和方法
调用构造方法调用当前类的其他构造方法,必须放在构造方法的第一条语句调用父类的构造方法,必须放在构造方法的第一条语句
查找范围从当前类开始查找从父类开始查找

Question4

  1. final 修饰的类可以被继承吗?可以继承其它类吗?

    final 修饰的类不能被继承,可以继承其它类。

  2. final 修饰的方法可以被重写吗?

    final 修饰的方法不可以被重写。

  3. final 修饰的变量相当于什么?

    相当于常量。

  4. final 修饰的引用类型变量可以改变其引用地址吗?可以改变对象的内部属性的值吗?

    final 修饰的引用类型变量不可以改变其引用地址,可以改变对象的内部属性的值。

Question5

修改后的代码见 ./Question 05/ 目录。

解答:

  • Lab 2 中的单例模式,或者说所有构造方法都是 private 时,不可能有子类。
  • final不完全可以视为所有构造方法都是 private 的类。二者都不能被继承、不能被扩展,但区别在于,final 类在有 publicprotected 的构造方法时可以被实例化,而所有构造方法都是 private 的类不能被外部实例化。

Question6

工程文件见 ./Question06/目录。

思考题: 如果 abShape 中的访问权限被设置为 private,在不添加新的属性的情况下,子类想要实现自己的 calcArea() 该怎么办?

可以在 Shape 中实现两个方法 getA()getB(), 返回 ab 的值,便可直接被外部方法调用。

Question7

工程文件见 ./Question07/ 目录。

  • 交通工具的测试类为 ./Question07/TestVehicles.java
  • 场景的测试类为./Question07/TestMotorbike.java