ユージン:
」私はこのJavaの例を持っているとしましょう:
interface Sink<T> {
void accumulate(T t);
}
public static <T> void drainToSink(Collection<T> collection, Sink<? super T> sink) {
collection.forEach(sink::accumulate);
}
二番目のパラメータがあることが宣言されているかに注意してください? super T
。私はこのようにそのメソッドを呼び出したいので、私はこれを必要とします:
Sink<Object> sink = .... // some Sink implementation
Collection<String> strings = List.of("abc");
drainToSink(strings, sink);
今、私は(私はと非常に小さな経験を持っている)kotlinと同じことを達成しようとしています:
interface Sink<T> {
fun accumulate(t: T)
}
fun <T> drainToSink(collection: List<T>, sink: Sink<T>) {
....
}
そして今、私はそれを使用しようとしています:
fun main(args: Array<String>) {
val sink = object : Sink<Any> {
override fun accumulate(any: Any) { }
}
val strings = emptyList<String>()
drainToSink(strings, sink)
}
(私はここkotlinについてあまりにも少し知っている限り)面白いことに、これは失敗しません。
私は本当に私のような宣言に何かを追加する必要があることを期待していたSink<in T>
、これは実際にあることをコンパイラを知ることができるようにだけConsumer
、またはあるin T
デフォルトでは、常にオン?
kotlinより良い私よりも知っている缶誰かが、正しい方向に私を指しますか?
ジョーンVernee:
私は私のコメントで言ったように、T
と推測されているAny
ここに。それは私のIDEがに明示的な型の引数を追加せたときに、私が見たものだdrainToSink
コール。
kotlinさんがいるのでList
、厳密プロデューサーである、それは不変であるので、それはそれとしての型パラメータを宣言しますout E
。あなたは、取得List<Any>
のためのパラメータの型としてdrainToSink
、それの罰金を割り当てることList<String>
とします。
val strings = emptyList<String>()
val x: List<Any> = strings // works
あなたが最初のパラメータの種類に変更した場合MutableList<T>
、共変の型パラメータを持っていない、あなたの例ではない失敗します。
fun <T> drainToSink(collection: MutableList<T>, sink: Sink<T>) {
....
}
val strings = emptyList<String>()
drainToSink(strings, sink) // type mismatch: Required: MutableList<Any>, Found: List<String>