This is an assignment to the Software Architecture class at the Technische Hochschule Nürnberg.
In this assignment we want to improve the previously implemented SimpleListImpl
of Assignment 2.
Back then, SimpleListImpl
was implemented to store references of type Object
, which in turn required a type cast on retrieval:
SimpleList sl = new SimpleListImpl();
sl.add(new MyClass());
MyClass k = (MyClass) sl.get(0);
Inside SimpleListImpl
, the knowledge about the actual class was lost, and worse: the following code would compile but produce a runtime exception:
SimpleList sl = new SimpleListImpl();
sl.add(new MyClass());
sl.add(new MyOtherClass());
MyClass k1 = (MyClass) sl.get(0); // all ok
MyClass k2 = (MyOtherClass) sl.get(1); // ClassCastException!
Generics help us to avoid both the type cast and the risk of runtime exceptions by checking the type at compile time.
For this assignment, start with the reference solution of assignment 2 and the abstract
model class Plant
.
- Create a fork of this repository (button in the right upper corner)
- Clone the project (get the link by clicking the green Clone or download button)
- Import the project to your IDE (remember the guide in assignment 1)
- Validate your environment by running the tests from your IntelliJ and by running
gradle test
on the command line.
To make a class generic, introduce a generic type (typically named T
) in the class or interface signature, and replace all affected actual types with the generic type.
- Make the following interfaces and classes generic
SimpleList
SimpleFilter
SimpleListImpl
SimpleIteratorImpl
Element
- Adopt the changes in the test class
SimpleListTests.java
- Remove the now unnecessary type casts
- Add a new method
addDefault
to theSimpleList
interface; the purpose is to add a default instance (using the default constructor) to the list
Hint: this method aims at the instantiation problem of generics.
In the second part we want to focus on generic and default
methods.
For this purpose we'll add an additional method map(...)
and move the method filter(...)
to the interface SimpleList
.
- Implement the
filter(...)
method asdefault
method in theSimpleList
interface
(remember to run the tests when you completed the refactoring to ensure that the result is still the same) - Add the
map(...)
method to theSimpleList
interface according to the given UML (default
method)
Themap(...)
method transforms every element of your list with the givenFunction<T,R>
to another element of typeR
and collects all elements in a newSimpleList
. - Optionally: Implement the the
sort(...)
method asstatic
utility method in theabstract
classCollectionsUtility
.
You may choose any sort algorithm: Bubblesort, Mergesort,...depending on your choice you may need to add some methods toSimpleList
andSimpleListImpl
(can you imagine why this class should beabstract
and optimally has aprivate
constructor?)
Remember, an untested implementation is worthless! Expand the given test suite to ensure that your algorithms are correct.