为什么在功能参数中的反类型参数在"out"中被考虑?位置? [英] Why are contravariant type parameters in function parameters considered in "out" position?
问题描述
我很难用英语来描述,但这是问题所在:
Hard for me to describe in english, but here's the issue:
class Consumer<in T> {
fun consume(t: T) {}
}
class Accepter<in T>() {
// ERROR: Type parameter T is declared as 'in' but occurs in 'out' position in type Consumer<T>
fun acceptWith(value: T, consumer: Consumer<T>) {}
}
可以这样修复:
fun <U : T> acceptWith(value: T, consumer: Consumer<U>) {}
但是我不明白这个问题.允许Consumer<T>
似乎并不安全.有人可以解释吗?
But I don't understand the issue. It doesn't seem unsafe to allow Consumer<T>
. Can someone explain this?
推荐答案
本身允许输入的函数参数在逻辑上等效于函数的返回值,这些函数的值显然处于出"位置.
Function parameters which themselves allow input are logically equivalent to return values for a function, which are obviously in "out" position.
考虑以下简单示例:
interface Worker<in T> {
fun work(output: Consumer<T>)
}
从逻辑上讲,它等同于
interface Worker<in T> {
fun work(): T
}
不论哪种情况,
work()
都可以输出一个值.
work()
can output a value in either case.
此失败的示例:
fun bad(anyWorker: Worker<Any>) {
val stringWorker: Worker<String> = anyWorker
stringWorker.work(Consumer { value: String -> /* value could be Any since it came from anyWorker! */ })
}
但是,我们可以通过为函数引入新的类型参数来解决此问题:
However, we can solve this by introducing a new type parameter for the function:
interface Worker<in T> {
fun <U : T> work(output: Consumer<U>)
}
现在,将仅允许work()
调用具有消费者必须能够使用的某些特定子类型T
的Consumer
.例如,让我们想象一下工作像原始问题一样接受了另一个论证,并且实际上做了一些事情:
Now, work()
will only be allowed to call the Consumer
with some specific subtype of T
that the consumer must be able to consume. For example, lets imagine that work takes another argument, as in the original question, and actually does something:
class Worker<in T> {
private val inputs = mutableListOf<T>()
fun <U : T> work(input: U, output: Consumer<U>) {
inputs += input
output.accept(input)
}
}
通过引入类型参数U
,我们可以确保input
和output
彼此一致,但仍允许Worker<Any>
扩展Worker<String>
.
By introducing the type parameter U
, we can ensure that input
and output
are consistent with respect to each other, but still allow Worker<Any>
to extend Worker<String>
.
这篇关于为什么在功能参数中的反类型参数在"out"中被考虑?位置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!