Generics Kotlin泛型返回类型与接收方匹配

Generics Kotlin泛型返回类型与接收方匹配,generics,kotlin,Generics,Kotlin,我正在尝试创建一个函数,如果接收器的数字为空,则返回默认值。但是,当我检查接收值的类型时,它与接收方不匹配,而是与作为参数传递的默认值匹配 fun <T : Number> T?.orDefault(value: T): T = this ?: value 当我尝试引入另一个扩展T的J时,仍然失败。使用上述主方法运行仍然失败 fun <T : Number, J : T> T?.orDefault(value: J): T = this ?: (value as T)

我正在尝试创建一个函数,如果接收器的数字为空,则返回默认值。但是,当我检查接收值的类型时,它与接收方不匹配,而是与作为参数传递的默认值匹配

fun <T : Number> T?.orDefault(value: T): T = this ?: value
当我尝试引入另一个扩展
T
J
时,仍然失败。使用上述主方法运行仍然失败

fun <T : Number, J : T> T?.orDefault(value: J): T = this ?: (value as T)

// Output:
-1
java.lang.Integer
fun T?.orDefault(值:J):T=this?:(值为T)
//输出:
-1
java.lang.Integer
在所有情况下,它都不会返回双精度。这里怎么了

编辑

我最后做了这样的事情:

// Output:
-1
java.lang.Integer
fun <T : Number, J : Number> T?.orDefault(value: J): T = this ?: (value as T)
fun <T : Number, J : Number> T?.orDefault(value: J): T = this ?: (value as T)
fun T?.orDefault(值:J):T=this?:(值为T)

这样,它可以确保返回类型与接收方类型相同。然而,唯一的缺点是空
Int
接收器默认接受
Double
,并强制转换为
Int
返回。

在第一种情况下,
orDefault()
要求接收器和参数的类型相同(
T
)。因此,当您使用
Double
接收器和
Int
参数调用它时,编译器会为类型参数
T
推断出它们最接近的公共超类(
Number
)。然后它直接返回给定的
Int
,如您所见

虽然你的第二个案例看起来更像你想要的,但我认为它仍然在为
T
推断
Number
,所以演员阵容没有任何效果


归根结底,我认为您不可能只用一个扩展函数就可以做您想做的事情。在Kotlin中不能将
Int
转换为
Double
(与Java不同);您需要调用它的
toDouble()
方法。您需要为每种接收器类型分别编写代码。

泛型不是最佳解决方案。由于
Number
只有7个子类,因此最好像这样重载扩展函数:

// Output:
-1
java.lang.Integer
fun <T : Number, J : Number> T?.orDefault(value: J): T = this ?: (value as T)
fun <T : Number, J : Number> T?.orDefault(value: J): T = this ?: (value as T)
第一路:

fun Int?.orDefault(value: Int) = this ?: value
fun Double?.orDefault(value: Double) = this ?: value
// do the same for Float, Long, Char, Short and Byte 
这将产生理想的行为

val default : Int = -1
val orDefault = b.orDefault(default.toDouble()) 
注意:您需要将
default
转换为
Double
,因为接收器是
Double
,它需要一个
Double
作为默认值

输出:

-1.0
双重的

第二条道路

如果要接受任何
编号
,并将其转换为接收器类型,请执行以下操作:

fun Int?.orDefault(value: Number) = this ?: value.toInt()
fun Double?.orDefault(value: Number) = this ?: value.toDouble()
// do the same for Float, Long, Char, Short and Byte 

最后,我做了这样的事情:

// Output:
-1
java.lang.Integer
fun <T : Number, J : Number> T?.orDefault(value: J): T = this ?: (value as T)
fun <T : Number, J : Number> T?.orDefault(value: J): T = this ?: (value as T)
fun T?.orDefault(值:J):T=this?:(值为T)
这在不重写所有数字类型的情况下工作,并返回正确的类型


唯一的问题是它可以接受数字类型中的任何默认值。与Int一样,它可以接受双精度值作为默认值,并返回其Int表示形式。

这很遗憾(