Spaces:
Running
Running
TurkuBasicOOPinJava / Week 7: Enum, Generic Type, Streams, write to file, class diagram /07A. Generics and Class Hierarchies????
| The use of 'generic type definitions' in classes naturally LIMITS the FUNCTIONALITY OF METHODS that use type definitions. | |
| Since the 'generic type' can be anything when an object is created from a class, | |
| we can't use through a variable of the type 'anything other than the features defined in the Object class'. | |
| =???????? | |
| => because Java doesn't know what T actually is at compile time, | |
| => you can't assume specific behavior (like calling .length() or + operations) unless explicitly told. | |
| VS | |
| => In Java, all classes inherit from 'Object'. | |
| => So if you have a generic type T, Java treats it as if it were an 'Object' | |
| => — meaning you can only safely call methods defined in 'Object', such as: | |
| .toString() | |
| .equals() | |
| .hashCode() | |
| => You cannot assume anything more specific (like .compareTo(), .length(), +, etc.) unless you bound the generic type to a dtype u want. | |
| The following code, for example, would give a compilation error: | |
| class Box<TYPE> { | |
| private TYPE value; | |
| public Box(TYPE value) { | |
| this.value = value; | |
| } | |
| public TYPE getValue() { | |
| return value; | |
| } | |
| public void setValue(TYPE value) { | |
| this.value = value; | |
| } | |
| public void isValueLongerThanZero() { | |
| // This gives a compilation error, because the method | |
| // length() is not in all classes | |
| if (value.length() > 0) { | |
| System.out.println("Longer than 0!"); | |
| } | |
| } | |
| } | |
| THE CODE GIVES A COMPILATION ERROR: | |
| The method length() is undefined for the type TYPE | |
| ================================================================================== | |
| However, we can LIMIT the DEFINITION of the generic type by using the 'extends' keyword. | |
| For example, the following 'generic definition' indicates that the 'implementing type' must inherit the class 'Person': | |
| class PersonContainer<T extends Person> { | |
| private T person; | |
| public PersonContainer(T person) { | |
| this.person = person; | |
| } | |
| public String giveName() { | |
| // Now this works, because T inherits 'Person' | |
| return person.getName(); | |
| } | |
| public String giveEmail() { | |
| return person.getEmail(); | |
| } | |
| } | |
| The type to be inherited can also be an 'interface', even though the keyword 'extends' is still used, confusingly. | |
| For example, types implementing the 'Comparable interface ' | |
| naturally have the method compareTo in use. | |
| Note that the generic definition T is also repeated in the name of the interface: | |
| class Comparator<T extends Comparable<T>> { | |
| public Comparator() {} | |
| public T giveGreater(T element1, T element2) { | |
| if (element1.compareTo(element2) < 0) { | |
| return element2; | |
| } | |
| else { | |
| return element1; | |
| } | |
| } | |
| } | |
| ================================================================================== | |
| Generics also involves other issues not covered in this section, | |
| such as statically, generically typed methods or wildcard characters. | |
| You can read more about these in Oracle's tutorial: | |
| https://docs.oracle.com/javase/tutorial/java/generics/index.html | |