Subtyping answers a practical Kotlin question: may this value go where that type is expected? Type B is a subtype of type A when a B value is valid wherever an A value is required. Every type is a subtype of itself; the reverse relationship is a supertype. The compiler applies this rule to assignments and function arguments. section 11.3.2
Use a more specific value where a general one is expected
```kotlin fun test(i: Int) { val n: Number = i // Int is a subtype of Number fun f(s: String) { } f(i) // does not compile: Int is not a subtype of String } ``` In straightforward class hierarchies, subtyping often follows subclassing: `Int` is a subtype of `Number`, and a class implementing an interface is a subtype of that interface, such as `String` and `CharSequence`. The important test is always usability at the required type, not merely a shared class name. section 11.3.2
Figure 11.5 B is a subtype of A if you can use it when A is expected. Since you can use an Int where a Number is expected, it is a subtype. Likewise, you can use an Int where an Int is expected; it is also a subtype of itself. Because you can’t use an Int where a String is expected, it can’t be considered a subtype.
Use the expected-type test visually: `Int` can stand in for `Number` and for itself, but not for `String`. section 11.3.2
A class name does not identify just one Kotlin type. `String` and nullable `String?` are distinct types, and generic classes produce types such as `List<Int>`, `List<String?>`, and `List<List<String>>`. Nullability has its own direction: non-null `A` is a subtype of `A?`, so a `String` can be assigned to `String?`; a possibly null `String?` cannot be used where `String` is required. section 11.3.2
For generic types, matching base names is not enough. Variance determines whether a type argument’s subtype relationship carries through, reverses, or does not apply. Kotlin’s read-only `List` is covariant: `List<String>` is usable where `List<Any>` is expected. That is safe for a function that only reads values. A `MutableList<String>` cannot be passed as `MutableList<Any>`, because a function could add an `Int` and leave a list that no longer contains only strings. section 11.3.1 section 11.4
Choose the interface that preserves type safety
```kotlin fun printContents(list: List<Any>) { println(list.joinToString()) } fun addAnswer(list: MutableList<Any>) { list.add(42) } val strings = mutableListOf("abc", "bac") printContents(strings) // safe through read-only List // addAnswer(strings) // rejected: it could insert an Int ``` Read-only and mutable collection interfaces therefore express more than available operations: they control which subtype substitutions are safe. section 11.3.1
Contravariance reverses the generic relationship for types that consume values. `Comparator<in T>` receives `T` values, so a comparator able to handle `Fruit` can also compare `Apple`: `Comparator<Fruit>` is a subtype of `Comparator<Apple>`. More generally, `Consumer<A>` is a subtype of `Consumer<B>` when `B` is a subtype of `A`. A function type combines both directions: its parameter is contravariant and its return type is covariant. section 11.3.4 section 11.4
Reuse a comparator written for a supertype
```kotlin val weightComparator = Comparator<Fruit> { a, b -> a.weight - b.weight } val apples: List<Apple> = listOf(/* ... */) println(apples.sortedWith(weightComparator)) ``` The comparator accepts any `Fruit`, so every `Apple` is already a valid input. This is the reverse of a producer-like covariant type, where a more specific type argument produces a more specific generic type. section 11.3.4
Kotlin supports declaration-site variance for a generic class as a whole and use-site variance for one particular use, serving the same broad purpose as Java wildcards. Type arguments are normally compile-time information because they are erased at runtime; inline reified type parameters are the stated exception for runtime type checks. section 11.0 section 11.4



