【问题标题】:General String extension conversion using reified typing使用具体类型的一般字符串扩展转换
【发布时间】:2018-06-19 12:23:59
【问题描述】:

在尝试实现通用字符串到数字字符串扩展方法时,我开始使用 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) 我无法找到正确的语法来将 reified T 限制为仅允许的类型 - 我想用尽 when 条件并删除 else->throw

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

这里有没有限制类型的方法和比较类类型的更好方法?

【问题讨论】:

    标签: kotlin kotlin-reified-type-parameters


    【解决方案1】:
    1. 只有在要处理的类型之间有共同的超类型时,才能约束 T。当然你不能给内置的IntFloat等类添加超类型,但是这些都是Numbers,你可以使用:

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

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

    2. 这部分问题的好消息,仅使用 ::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)")
          }
      }
      

    【讨论】:

    • 非常感谢 - 我会将您的所有建议投入生产。
    猜你喜欢
    • 2011-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-10
    • 2014-12-08
    • 1970-01-01
    • 2018-12-01
    • 2017-08-25
    相关资源
    最近更新 更多