@gidds brought to my attention that the where
keyword makes an intersection type, not a union type. I assumed the opposite. The docs should be more explicit.
Under the online documentation for Generics: Constraints, it says, “Only one upper bound can be specified inside the angle brackets. If the same type parameter needs more than one upper bound, we need a separate where -clause”
I recommend adding a little more, like, “A where clause creates an intersection type - each sub-clause must be satisfied. The type parameter specified this way must be a subtype of A and B and C etc.”
This little code snippet proves the above:
// Create some interfaces...
interface A {
val foo: String
}
interface B {
val bar: Int
}
// Type T must be both and A and a B
fun <T> baz(t: T): String where T : A, T : B {
return t.foo + t.bar
}
// Now test baz()
fun fud(): String {
// ERROR: Inferred type is not a subtype of B
// val t = object: A {
// override val foo: String = "hi"
// }
// ERROR: Inferred type is not a subtype of A
// val t = object: B {
// override val bar: Int = 5
// }
// Works - t must be a subtype of both A and B.
val t = object: A, B {
override val foo: String = "hi"
override val bar: Int = 5
}
return baz(t) // returns "hi5"
}