常规 使用具体类型化的字符串扩展转换



在尝试实现通用字符串到数字字符串扩展方法时,我开始使用 reified 关键字。以下内容编译并运行,但我想在生产代码中使用它之前对其进行改进:

inline fun <reified T> String.convertTo():T {
return when(T::class.simpleName){
Int::class.simpleName->{(this.toIntOrNull() ?: 0) as T}
Float::class.simpleName->{(this.toFloatOrNull() ?: 0f) as T}
Double::class.simpleName->{(this.toDoubleOrNull() ?: 0.0) as T}
else -> throw IllegalArgumentException("Can't convert type $(T::class.simpleName)")
}
}

我喜欢这个的简洁调用者代码:

val time:Int by lazy {((evaluateExpression("time").convertTo<Float>().times(1000f))).toInt()}

如果在这种情况下可能的话,我想做两件事:

1(我无法找到正确的语法来将化T限制为仅允许的类型-我想用尽when条件并删除else->抛出

2( T::class.java不能正确与其他类型的类类型(即 Int::class.java(进行比较,所以我求助于比较 simpleName 字符串 - 什么会更好?

有没有办法限制类型以及在这里比较类类型的更好方法?

  1. 只有在要处理的类型之间具有公共超类型时,才能约束T。当然你不能在内置的IntFloat等类中添加超类型,但这些都是Number,你可以使用:

    inline fun <reified T : Number> String.convertTo(): T
    

    但是,ByteLongShort也是如此,所以你仍然需要处理这些......但更重要的是,Number只是一个抽象类,而不是一个密封的类(如果需要,你可以合理地实现你自己的类(,所以在这种情况下,when表达式无法详尽无遗。因此,不幸的是,您只需要保留else分支即可。

  2. 对于
  3. 问题的这一部分,好消息是,仅使用::class并比较KClass实例应该有效(我还删除了一些大括号(:

    inline fun <reified T : Number> String.convertTo(): T {
    return when (T::class) {
    Int::class -> (this.toIntOrNull() ?: 0) as T
    Float::class -> (this.toFloatOrNull() ?: 0f) as T
    Double::class -> (this.toDoubleOrNull() ?: 0.0) as T
    else -> throw IllegalArgumentException("Can't convert type $(T::class.simpleName)")
    }
    }
    

最新更新