Suppose I have a class Message
and a class Channel<T : Message>
.
Now, how come I can't cast Channel<out Message>
to Channel<Message>
without an Unchecked Cast warning?
Shouldn't this cast always be safe since Channel<out Message
can only contain objects of type Message
or subclasses of type Message
?
No, and here is proof.
class Channel<T : Message> {
fun send(t: T)
fun receive(): T
}
class Apple : Message()
class AppleChannel : Channel<Apple>() {
...
}
val appleChannel = AppleChannel()
val outMessageChannel: Channel<out Message> = appleChannel // MUST WORK
val messageChannel: Channel<Message> = outMessageChannel
// you say this should work, but...
messageChannel.send(Orange())
// sending orange on a channel that only knows how to send apples!
// Error!
The only consistent thing to do is to not allow the conversion of Channel<out Message>
to Channel<Message>
in this scenario.
If it were defined as Channel<out T: Message>
, then this would be safe, but trying to define send
would cause an error.