Tujuan saya adalah agar metode antarmuka menerima tipe kelas implementasi. Berikut kode yang saya tulis sejauh ini:

internal interface Diff<Diff> {   //in Java I was using <? extends Diff>
    fun lessThan(other: Diff): Boolean
}

private class ADiff(private val value: Int) : Diff<ADiff> {

    override fun lessThan(other: ADiff): Boolean {
        return value < other.value
    }

}

//B can now accept even int types which is not desired
private class BDiff(private val value: Int) : Diff<Int> {

    override fun lessThan(other: Int): Boolean {
        return value < other
    }

}
2
Jaguar 26 November 2017, 08:52

1 menjawab

Jawaban Terbaik

Alasan mengapa ini "berfungsi" di Java adalah karena <T extends Diff> menggunakan tipe mentah Diff. Jangan lakukan ini!


Yang paling dekat yang bisa Anda dapatkan adalah dengan menggunakan tipe rekursif terikat:

interface Diff<T : Diff<T>> {
    fun lessThan(other: T): Boolean
}

Masalahnya adalah, Anda dapat mengganti subtipe Diff lainnya.

Namun, saat menggunakan Diff, gunakan batasan tipe generik T : Diff<T>:

fun <T : Diff<T>> diffUser(diff1: T, diff2: T) {
    println(diff1.lessThan(diff2))
}

Dan Diff apa pun yang tidak mengimplementasikan Diff<SameType> tidak akan diterima.

Contoh:

class CDiff(private val value: Int) : Diff<DDiff> { // <-- Wrong type!
    override fun lessThan(other: DDiff) = value < other.value
}

class DDiff(val value: Int) : Diff<DDiff> {
    override fun lessThan(other: DDiff) = value < other.value
}

fun test() {
    diffUser(CDiff(3), CDiff(4)) // <-- Doesn't compile due to the generic constraint
    diffUser(DDiff(3), DDiff(4))
}

Pendekatan yang sama ini digunakan oleh class Comparable.


Meskipun ini berhasil, yang Anda benar-benar inginkan adalah "tipe mandiri" dan ini tidak didukung, meskipun ada di peta jalan di beberapa titik. Saya yakin JetBrains menolak permintaan untuk ini, meskipun saya tidak dapat menemukan laporan bug.

Jawaban ini merinci solusi di Java menggunakan pola CRT, meskipun belum tentu mengetik aman.

3
Moira 26 November 2017, 13:00