Challenge 3: Covariance with out — Solution open class Animal(val name: String) class Cat(name: String) : Animal(name) interface Shelter { fun adopt(): T } class CatShelter : Shelter { override fun adopt(): Cat = Cat("Whiskers") } fun main() { val catShelter: Shelter = CatShelter() val adopted = catShelter.adopt() println("Adopted: ${adopted.name}") } /* Output: Adopted: Whiskers Notes: - Without "out" on Shelter, "val catShelter: Shelter = CatShelter()" would be a compile error, because Shelter and Shelter would be treated as completely unrelated types (invariance, the default). - "out T" is safe here specifically because T only ever appears as a return type (adopt(): T) — Shelter never accepts a T as a parameter anywhere, so there's no way to put the "wrong" kind of Animal into it through the wider Shelter reference. - adopted is typed as Animal (the type seen through the Shelter reference), even though the actual runtime object is a Cat — this is the same idea as returning a String from something typed as Any. */