Ex 4: Some Body Once Told Me
Basic Information
- Deadline: 8 October 2024, Tuesday, 23:59 SGT
- Difficulty: ★★★
Prerequisite
- Caught up to Unit 27 of Lecture Notes.
- Familiar with CS2030S Java style guide.
Goal
The goal of this exercise is to build a simple immutable generic container.
Tasks
Our container is storing some value of reference type. We shall call this container Some
. It is a generic wrapper class with a single type parameter T
(i.e., Some<T>
). At the beginning, this will not be a useful container, but do not worry, we will slowly add more functionalities.
Task 1: A Simple Container
Implement a generic class Some<T>
that
- contains a field of type
T
that is declaredprivate
andfinal
to store the content. - overrides the
boolean equals(Object)
method fromObject
to compare if two containers are the same in the way described below.- Two containers are the same if the contents are equal to each other, as decided by their respective
equals
method.
- Two containers are the same if the contents are equal to each other, as decided by their respective
- overrides the
String toString()
method fromObject
so it returns the string representation of its content, between[
and]
. - provides a class method called
some
that returns a container with the given object.- You may assume that no
null
value will be given for now .
- You may assume that no
Factory Method
The method some
is called a factory method. A factory method is a method provided by a class for the creation of an instance of the class. Using a public constructor to create an instance necessitates calling new
and allocating a new object on the heap every time. A factory method, on the other hand, allows the flexibility of reusing the same instance. The some
method does not currently reuse instances but this will be rectified in subsequent exercise.
With the availability of the of factory method, Some<T>
should keep the constructor private
.
Sample Usage | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
You can test your Some<T>
more comprehensively by running:
Test1.java | |
---|---|
1 2 |
|
There shouldn't be any compilation warning or error when you compile Test1.java
and all tests should prints ok
.
Task 2: Transformation
Now, we are going to write an interface (along with its implementations) and a method in Some
that allows a container to be transformed into another container, possibly containing a different type.
Step 1: Transformer Interface
First, create an interface called Transformer<T, U>
with an abstract method called transform
that takes in an argument of generic type T
and returns a value of generic type U
.
Part 2: Mapping Method
Second, write a method called map
in the class Some
that takes in a Transformer
, and use the given Transformer
to transform the container (and the value inside) into another container of type Some<U>
. You should leave the original container unchanged.
Sample Usage | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
|
You can test your Some<T>
more comprehensively by running:
Test2.java | |
---|---|
1 2 |
|
There shouldn't be any compilation warning or error when you compile Test2.java
and all tests should prints ok
.
Part 3: Flexible Method
Make sure that you make the method signature as flexible as possible. Follow the PECS principle after you determine which type (i.e., T
or U
) acts as producer or consumer (or both?).
Flexible Usage | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
|
You can test your Some<T>
more comprehensively by running:
Test3.java | |
---|---|
1 2 |
|
There shouldn't be any compilation warning or error when you compile Test3.java
and all tests should prints ok
.
Task 3: Jack in the Box
The Transformer
interface allows us to transform the content of the container from one type into any other type, including a Some<T>
! You have seen examples above where we have a container inside a container: Some.some(Some.some(0))
.
Now, implement your own Transformer
in a class called JackInTheBox<T>
to transform an item into a Some
containing the item. The corresponding type T
is transformed into Some<T>
. This transformer, when invoked with map
, results in a new Some
within the Some
.
Sample Usage | |
---|---|
1 2 3 4 |
|
You can test your JackInTheBox<T>
more comprehensively by running:
Test4.java | |
---|---|
1 2 |
|
There shouldn't be any compilation warning or error when you compile Test4.java
and all tests should prints ok
.
Skeleton for Programming Exercise 4
A set of empty files has been given to you. You should ONLY edit these files. You must NOT add any additional files.
Do NOT Add
Only edit the given files, do not add any additional files.
Some files (e.g., Test1.java
, A.java
, CS2030STest.java
, etc) are provided for testing.
You may edit them to add your own test cases, but we will be using our own version for testing.
Following CS2030S Style Guide
You should make sure your code follows the given Java style guide.
To check for style,
Style Check | |
---|---|
1 |
|
Suppressing Warnings
If you design your code correctly, you do not need any @SuppressWarnings
. If you have any, you may want to check your design again.
Further Deductions
Additional deductions may be given for other issues or errors in your code. This include but not limited to
- run-time error.
- failure to follow instructions.
- improper designs (e.g., not following good OOP practice).
- not comenting
@SuppressWarnings
. - misuse of
@SuppressWarnings
(e.g., not necessary, not in smallest scope, etc).
Documentation (Optional)
Documenting your code with Javadoc is optional for Programming Exercise 4. It is, however, always a good practice to include comments to help readers understand your code.