# In-Projection

An in-projection is a kind of type projection that makes a generic contravariant, but also causes any functions that return the type parameter to return it as a more abstract type.

Why is it called a projection? Because it’s a limited view of a real object. In regular life, a shadow is a kind of projection - it’s a limited two-dimensional representation of an actual three-dimensional thing. Just like a shadow lacks some qualities of the object that it’s created from, an in-projection lacks the normal return types of the type it’s projecting.

## Example

To demonstrate in-projections, let’s create an extension function on a `Dog` class, which will allow us to add it to a Java `Queue`:

``````fun Dog.addToQueue(queue: Queue<in Dog>) = queue.add(this)
``````

Notice the type of the parameter `queue` above - it’s not `Queue<Dog>`, but `Queue<in Dog>`. Because we added the `in` variance annotation to the type argument `Dog`, we’ve got an in-projection of a dog queue. That means that this function can accept a `Queue<Dog>`, as you’d expect, but it can also accept a `Queue<Animal>`!

``````val bruno = Dog("Bruno")

val dogQueue: Queue<Dog> = LinkedList()

val animalQueue: Queue<Animal> = LinkedList()
``````

If you were to remove `in` from the type argument, this last line would no longer compile, because `Queue<Animal>` isn’t normally a subtype of `Queue<Dog>`.

## The Limitation: `in` means “out” positions are crippled

In order to get this subtyping, we had to make a trade-off: any time we pull a pet off of the queue inside this function, we lose the type safety.

Let’s try it. Before we add our dog to the queue, we’ll take a peek to see who’s at the head of the queue.

``````fun Dog.addToQueue(queue: Queue<in Dog>) {
val nextDog: Any? = queue.peek() // This returned `Any?` instead of `Dog`!
}
``````

This points out an important limitation with in-projections:

• Calling `peek()` on a `Queue<Dog>` returns a `Dog`, but
• Calling `peek()` on a `Queue<in Dog>` returns an `Any?`

This is the case for all functions and getters that put that type parameter in the “out” position (i.e., that return an object whose type is that type parameter).

Why is this the case?

Since our `addToQueue()` function uses an in-projection, it means it can accept a queue of `Dog` or anything higher on its type hierarchy. So, it’ll accept a `Queue<Dog>`, `Queue<Animal>`, or `Queue<Any?>`. For example:

``````val queue: Queue<Any?> = LinkedList()
This queue has an integer in it! Since the queue can have anything at all in it, the safest type that we can assume when pulling an item out is `Any?`.
1. You want contravariance on a generic. For example, you want to accept `Queue<Animal>` in addition to `Queue<Dog>`.
3. You don’t need to get the item out of the generic, or if you do, you’re cool with it having type `Any?`. In-projections will only allow you to pull that type parameter out as `Any?`.