Параметры функции, которые сами позволяют вводить, логически эквивалентны возвращаемым значениям для функции, которые, очевидно, находятся в положении «вне».
Рассмотрим этот простой пример:
interface Worker<in T> {
fun work(output: Consumer<T>)
}
Этологически эквивалентно
interface Worker<in T> {
fun work(): T
}
work()
can output значение в любом случае.
Пример этого сбоя:
fun bad(anyWorker: Worker<Any>) {
val stringWorker: Worker<String> = anyWorker
stringWorker.work(Consumer { value: String -> /* value could be Any since it came from anyWorker! */ })
}
Однако мы можем решить эту проблему, введя новый параметр типа для функции:
interface Worker<in T> {
fun <U : T> work(output: Consumer<U>)
}
Теперь work()
будет разрешено вызывать Consumer
только с некоторым конкретным подтипом T
, которыйпотребитель должен иметь возможность потреблять.Например, давайте представим, что работа принимает другой аргумент, как в исходном вопросе, и фактически что-то делает:
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>
.