How to deal with generic bounds migrating from Java to Kotlin?

前端 未结 1 429
名媛妹妹
名媛妹妹 2021-01-22 03:57

My goal is to have the interface methods accept the class type of the implementation. Here\'s the code I have written so far:

internal interface Diff         


        
相关标签:
1条回答
  • 2021-01-22 04:20

    The reason why this "worked" in Java was because <T extends Diff> uses the raw type Diff. Don't do this!


    The closest you can get is to use a recursive type bound:

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

    The problem is, you can substitute any other subtype of Diff.

    However, when using the Diff, use the generic type constraint T : Diff<T>:

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

    and any Diff that doesn't implement Diff<SameType> will not be accepted.

    Example:

    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))
    }
    

    This same approach is used by the Comparable class.


    Although this works, what you really want is a "self type" and this is not supported, although it was on the roadmap at some point. I believe JetBrains denied the request for this, though I cannot find the bug report.

    This answer details a workaround in Java using the CRT pattern, though it is not necessarily type safe.

    0 讨论(0)
提交回复
热议问题