Summary
In this chapter, we have learned why generics exist and we have discussed various ways of defining a generic class and interface, and declaring generic types. We know how to deal with subtyping relations by using use-site and declaration-site variance modifiers. We learned how to deal with type erasure and how to preserve generic types at runtime using reified type parameters.
In the next chapter, we will discuss one of the most exciting Kotlin features, extensions. This feature allows us to add new behavior to an existing class. We will learn how we can implement new methods and properties for any given class, including final classes from the Android framework and third-party libraries.