D5 - Generic Types (Joker), Inheritance (Super VS Extend)

Software, Java

*Happy new year everyone! *

Jokers As Generic Types

So we've already seen generic types as such:

public class SomeClass<T> {
    public void func1(List<T> lst) {...}
}

As we already know, the List in the function argument above ressemble a list of a specific object. Which object? That is defined by the class instance initialized. Once set, that same type will pass on to func1.

In some cases, we would like to use a type that is unrelated to the class, and instead is function specific, like so:

public class SomeClass{
    public static <T> void func1(List<T> lst){...}
}

Here, List is defining a "new" type T within it's signature. Note that the written is not related to the returned type (as the latter is void). It simply allows the given List to be a list of any desired type(e.g. String, Interger, etc.). *On a side note, static function always need their own definition of generic types, even if the class they're in has one defined already.

For that exact purpose, Java has the "Joker type". When we want to allow the function to recieve any type of object, we pass it as "<?>":

public class SomeClass{
    public static <T> void func1(List<T> lst){...}
    public static void func2(List<?> lst){...}
}
// func1 and func2 are perfectly identical!

"So why would we ever use the joker type if we can specify a new generic for each functon?" you ask? consider the next example:

public class SomeClass{
    public static <T> void func1(List<T> lst1, List<T> lst2){...}
    public static void func2(List<?> lst1, List<?> lst2){...}
}
// func1 and func2 are different!

This time, func1may be allowing any type - but it is restriction the arguments to be 2 lists of the same type (both of the lists would have to be List, for example). func2 however, is allowing any type (like func1) but the 2 lists can be of different types from each other. One list could be of and the other of (of course they could also be containing identical types).

As seen above the joker type has a wider range of possibilites, it doesn't mean we should always use it, that would depend on the specific use case.

Inheritance (Super VS Extend)

To explain the difference between super and extend based inheritance, I want to present an example.

class Organism{}
class Human extends Organism{}
class Weeb extends Human{}
// Organism has some functionality.
// Human has Organism's functionality and more.
// Weeb has both Human's & Organism's functionality, and even more!

Let's say we're defining a new function that recieves a list of joker(any type), which extends Human:

public static void func1(List<? extends Human> lst) {...}

func1 would accepts lists of humans, and anything that extends them, in this case - weebs.

Now let's learn about super:

public static void fun1(List<? super Human> lst) {...}

Now, func1 would accept lists of humans, and anything that human extends. Which means lists of humans, organism or object (since any new class we define is an extention of Object by default). So to sum it up, super is used when we want to use a type X or the more generic types it (X) is inherited from. We use extends when we want to use a type(Y), or any type that inherit from it(Y).

2022 just hit! Happy new year everyone - as this year resolution I am going to keep on learning and writing every-single-day. Good luck future me <3

RwK