本次 Lab 时长为 2 周,DDL 为 11 月 6 日 23:59。
附件下载(包括问答题和实验报告模板):https://bhpan.buaa.edu.cn/link/AA96D0CA694BB74ABFA070F38B6C527AC6
Object
类Object
类中方法的能力本实验假设你明白:
final
的(除非是匿名类的方法的参数)本次实验不会涉及以下内部类的常用技巧:
也不会涉及以下特殊情况:
阅读下面这段代码,回答问题。
1 | class Outer { |
在注释部分填写代码,使程序先后输出 30、20、10。提交包含代码和运行结果的截图。
注意:
阅读下面这段代码,回答问题。
1 | interface Inter { |
在注释部分填写代码,使程序输出 DuluDulu
。提交包含代码和运行结果的截图。
注意:
本题与 Lab 6 的一道附加题相同,不要求提交代码或解答,但建议实操或思考其实现。
在前面实验的 Shape
的基础上,定义一个满足如下需求的 IShapeFactory
接口:
Shape makeShape(double a, double b)
,返回一个由 a 和 b 指定大小的 形状;
用单例模式 + 工厂方法模式的思想修改矩形、椭圆、菱形类:
每一个类都增设一个 private static IShapeFactory factory
字段
类中的
factory
用于生成该类的形状对象,比如Rectangle
类中的factory
,其makeShape
方法返回Rectangle
对象,直接使用匿名类为factory
进行静态初始化,不允许像 Extra 2 那样定义工厂类
进行其他的修改,使外界的其他类能够获取到 factory
并成功构造形状对象
选择你认为合适的方式编写测试类:
ShapeFactoriesTest.makeShape
方法。使用匿名类,依然是为每一个形状创建了一个对应的工厂,因此本质上依然是工厂方法模式,区别在于不用显式定义新的类(据说编码过程中,起名字是最麻烦的事情)。
工厂方法模式的应用中,每一种工厂通常只有一个实例,因此它经常和单例模式一起被使用。
这是一个主动要求大家造轮子的题,因此不允许继承或组合任何 Java 自带的容器(除了数组)。
关于内部类实现迭代器,可以参考:An iterator that is an inner class。
在 Shape
的基础上,定义一个满足如下需求的 ShapeSequence
类:
private Shape[] shapes
ShapeSequence(int size)
size
用于指定 shapes
的最大长度,如果 size
是负数,那么按照 0
来处理。shapes
进行初始化赋值,在其他过程中 shapes
的大小不应该被改变public void add(Shape shape)
shapes
中添加一个新的元素shapes
被填满时,什么都不做public String toString()
[Type, Type,...]
Type
是形状类型的全小写英文单词,比如 rectangle、ellipse
public SequenceIterator iterator() {return new SequenceIterator(); }
private class SequenceIterator
,它用于序列遍历的迭代器
0
public boolean isEnd()
,迭代器完成遍历时,返回 true
public Shape current()
,返回当前迭代器指向位置的 Shape
对象
isEnd()
是 true
时,访问 current
是非法操作public void moveNext()
,使迭代器移动到下一个元素的位置
isEnd()
是 true
时,什么都不做public boolean equals(Object o)
,当 o
是 SequenceItetator
类型的、且 o
和 this
的外部类对象相同、且 o
和 this
的位置相同时,返回 true
对于 ShapeSequence
的 iterator
方法,由于内部类是 private
的,如果直接返回 SequenceIterator
,是无法编译通过的。因此,你可能需要使用接口来进行实现的隐藏,具体可以参考 An iterator that is an inner class。为此,你可以更改上文给出的需求。
编写测试类并描述你的测试计划。提交项目代码文件夹。
注意:toString
和 equals
是 override 继承自 Object
的方法,尽量避免出现诸如 ToString
、 equals
的参数类型不是 Object
等情况。
题目中省略了一些实现上必要但是方式不唯一的属性:比如你可以在 ShapeSequence
类中声明一个 int
属性来表示当前容器被填充到了什么位置;给 SequenceIterator
一个 int
属性表示当前迭代器指向的位置,当使用 isEnd
时,判断迭代器位置和外部类容器的填充位置进行比较。当然,你可以按自己的想法设计。
题外话
- 本题的目的是进行内部类、
Object
相关的综合实践。- 后续容器和泛型课程中,会引入可变长容器以及匿名类实现的迭代器。
- 虽然我们上机并不评测程序的性能,但是在实现本题的
toString
时,还是推荐考虑使用StringBuilder
。- 你可以考虑一下不使用内部类时要如何实现迭代器:内部类为这种数据访问是否带来了足够的便利?(不要求作答)
- 为什么
SequenceIterator
被限定为了private
?(不要求作答)