I want to start with what I know, or at least I think I know, so what I'm asking would be more clear.
First of all, I know that you can declare a variable of a supertype and assign an object of a subtype to take advantage of polymorphism with Inheritence and Interfaces.
I know that generics provide type safety because the type parameters are invariant by definition, so where A is a subtype of B,
Foo<A>is not necessarily a subtype ofFoo<B>, and may not be used in place depending on mutability of the object. With this, possible exceptions that could arise at runtime due to dynamic dispatching can be caught in compile time.They also help to define a generic logic for different types: Like in Lists where you have collections of type A objects, but it doesn't change the implementation for type B objects.
Also, I understood why
MutableList<String>doesn't count as the subtype ofMutableList<Any>because that could result in cases where you create a variable with typeMutableList<Any>that holds a reference to aMutableList<String>object, and add anIntelement to a List of Strings, which is obviously a problem.I also understood why List version of the previous example works because Lists are immutable so you can't make any modification to the object that could result in type mismatches.
Lastly, I know that type parameters with
incan only be used as function parameters, being consumed, and the ones withoutcan be used as the function return types, being produced.
Now to the part what I don't understand:
I didn't quite understand what the words consumer and producer actually means in terms of
inandout. What does it mean for a type to be in consumed or produced position? Does that mean the object with that type can only be read or write only? Does that have anything to do with the object at all?What would be the behaviour of the object if, let's say, we don't define it using
inorout, or, opposite, we define it usinginorout, not talking about the subtype-supertype relationship that I explained above.
I spend the last few days looking at different explanations of this, but I found the lack of examples a big problem, especially because that's how I usually learn.
I can use these concepts in code, but the lack of underlying knowledge or the logic greatly disturbs me, so please, if you decide to take the time to write an explanation, provide it with examples and counter examples of why or how a certain idea works.