首页 文章

Kotlin中泛型类的扩展函数

提问于
浏览
9

我的扩展功能在下面有什么问题

class Foo<T> {
    fun <T> Foo<T>.plus(that: Foo<T>): Foo<T> = throw Exception()

    init {
        Foo<Int>() + Foo<String>()  // A receiver of type Foo<T> is required
    }
}

Update

我想知道为什么它与常规扩展函数不同,其中T成功地被推断为 Any 并且想要实现相同的行为,例如: G . T被推断为Foo <Any>

class Foo {
    fun <T> T.foo(that: T): T = throw Exception()

    init {
        "str" foo 42
    }
}

2 回答

  • 16

    问题是仿制药如何运作的核心问题 .

    class Foo {
        fun <T> T.foo(that: T): T = throw Exception()
    
        init {
            "str" foo 42
        }
    }
    

    这是有效的,因为编译器可以找到适合函数签名和参数的 T :它是 Any ,函数变成了这个:

    fun Any.foo(that: Any): Any = ...
    

    现在, StringAny 的子类型, IntAny 的子类型,因此该函数适用于参数 .

    但在你的第一个例子中:

    class Foo<T> {
        fun <T> Foo<T>.plus(that: Foo<T>): Foo<T> = throw Exception()
    
        init {
            Foo<Int>() + Foo<String>()  // A receiver of type Foo<T> is required
        }
    }
    

    它's all different. There' s没有 T . 让我们天真并尝试 Any

    fun Foo<Any>.plus(that: Foo<Any>): Foo<Any> = ...
    

    现在, FooT 中是不变的,所以 Foo<Int>not Foo<Any> 的子类型,事实上除了 Int 之外没有类型 T 会使 Foo<T> 成为 Foo<Int> 的超类型 . 所以, T 必须完全 Int ,但它也必须完全 String 由相同的逻辑(因为第二个参数),所以没有解决方案,并且该函数不适用 .

    您可以通过在 T 中制作 Foo 共变体来使其工作:

    class Foo<out T> {
        fun <T> Foo<T>.plus(that: Foo<T>): Foo<T> = throw Exception()
    
        init {
            Foo<Int>() + Foo<String>()  // A receiver of type Foo<T> is required
        }
    }
    

    这对 Foo 成员的可能签名施加了一些限制,但如果您对它们没有问题,则可以解决您的问题 .

    有关详细信息,请查看此链接:http://kotlinlang.org/docs/reference/generics.html

  • 0

    您的方法 plus 要求参数具有与接收方相同的泛型类型参数 T . 因此,您无法将 Foo<String> 添加到 Foo<Int> .

    如果您希望能够添加所有类型的 Foo ,那么您需要声明扩展函数,如下所示:

    operator fun <T,R> Foo<T>.plus(that: Foo<R>): Foo<T> = throw Exception()
    

相关问题