代码之家  ›  专栏  ›  技术社区  ›  jchristof

使用归一化类型的通用字符串扩展转换

  •  0
  • jchristof  · 技术社区  · 8 年前

    当尝试将通用字符串实现为数字字符串扩展方法时,我开始使用Ri化关键字。以下是编译和运行的,但我希望在将其用于生产代码之前对其进行改进:

    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)")
        }
    }
    

    我喜欢consise呼叫者代码:

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

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

    1)我无法找到正确的语法来将reified t限制为只允许的类型-我想用尽when条件并删除else->throw

    2)t::Case.java不能正确地与其他类型的类类型(即int::类.java)进行比较,所以我求助于比较简单名字串——什么更好?

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

    1 回复  |  直到 8 年前
        1
  •  3
  •   zsmb13    8 年前
    1. 只能约束 T 如果要处理的类型之间有公共父类型。当然,不能将超类型添加到内置 Int , Float 等课程,但这些都是 Number S,您可以使用:

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

      然而,也有 Byte , Long 和 Short ,所以你还是要处理那些…但更重要的是, 数 只是一个抽象类,而不是一个密封类(如果需要的话,您可以合理地实现自己的类),因此 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)")
          }
      }