我们能在Kotlin中使用中缀泛型方法吗?

7
编译器接受中缀和通用方法,但是如何使用它的语法呢? 例如,给出这两个相同的方法(取任意通用类型的模数):
infix inline fun Int1.plus1(i: Int1) = Int1(this.value + i.value)
infix inline fun <U> Int1.plus2(i: Int1) = Int1(this.value + i.value)

我可以写:

我会写:

Int1(3).plus1(Int1(4))
Int1(3) plus1 Int1(4)
Int1(3).plus2<Int>(Int1(4))

但是这个调用无效:
Int1(3) plus2<Int> Int1(4)

有人能解释一下为什么吗?
1个回答

5

简而言之,是的,我们可以。

首先,对于这样的方法进行参数化是没有意义的。

infix fun <U> Int.foo(i: Int) = ...

由于 foo 从未使用类型参数 U,因此调用者和参数类型都已定义

当您给方法加上类型参数时,可以将其签名中的类型与泛型参数连接起来,例如:

infix fun <U> U.foo (other: U) = ...

或者至少其中之一。
infix fun <U> Int.foo (other: U) = ...
infix fun <U> U.foo (other: Int) = ...

编译器将根据参数和/或调用对象类型猜测U的类型

在您的情况下,编译器无法猜测U的类型,因为它既未连接到调用者也未连接到参数


1
但是假设您有一个扩展了Int1的类Int2。然后您有这个函数:infix inline fun <reified U> U.print(i: Int) = println("${U::class} $i")。如果您想要UInt1,则可以像这样调用它:Int2(5).print<Int1>(4)。是否可能使用中缀符号进行此调用? - marstran
那不起作用。该参数是普通的 Int。问题在于类型为 U 的接收器。我需要转换它吗?似乎有点奇怪,只有在处理中缀函数时才需要使用转换。 - marstran
没错。 :) 我觉得很奇怪,我不能像 Int2(5) print<Int1> 4 那样写。这似乎是一个绕过强制转换的方法。 - marstran
1
但是如果我进一步举例(尽管现在有点荒谬)。你如何使用中缀符号调用此函数?infix inline fun <reified U> Int.print(i: Int) = println("$this ${U::class} $i")。使用普通符号调用它可以正常工作:5.print<String>(4)打印出5 class kotlin.String 4 - marstran
将函数参数化为在输入参数中未使用但仅在返回类型中使用的类型是有意义的。例如,我想要一个com.jayway.jsonpath.JsonPath#read的中缀函数,它接受两个字符串但返回一个通用类型(将结果转换为指定类型)。似乎这样的函数无法使用中缀符号调用。 - Dario Seidl
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接