¿Cómo extiendo la class Kotlin Number o uso generics para crear un getter de propiedad simple que operará en todas las subclasss Number?

Estoy tratando de aprender más sobre extensiones de classs abstractas de Kotlin y generics mediante la construcción de methods muy simples y captadores de properties que extienden las classs integradas. En su mayoría he tenido éxito, pero estoy confundido por la class Número. Mi propiedad de testing Number.sgn está destinada a devolver el signo (1 o -1 como Int) de cualquier subclass de Number. Para simplificar, los negativos deberían devolver -1, mientras que los numbers positivos y 0 deberían ser 1. No estoy particularmente interesado en el caso de uso de este método, sino en la comprensión de cómo escribir algo simple como este, y por qué mi código genera el error lo hace. La única import en mi module es kotlin.text.* Y el post de error que recibo se refiere a un conflicto allí. Simplemente no entiendo por qué entra en conflicto y cómo superarlo, aunque supongo que es un error de novato.

Primero escribí el código para extender la class Int, que funciona bien:

inline val Int.sgn get() = if (this<0) -1 else 1 // sign of number

Luego intenté generalizar y moverlo a la class Número, así:

inline val Number.sgn get() = if (this<0) -1 else 1 // doesn't compile

y el error de compilation es el siguiente:

unresolved reference. None of the following candidates is applicable because of receiver type mismatch: public fun String.compareTo(other: String, ignoreCase: Boolean = ...): Int defined in kotlin.text inline fun Number.sgn() = if (this<0) -1 else 1 ^

Luego intenté un enfoque diferente, usando generics:

inline val <T:Number> T.sgn get() = if (this<0) -1 else 1

y recibí el mismo error del comstackdor:

error: unresolved reference. None of the following candidates is applicable because of receiver type mismatch: public fun String.compareTo(other: String, ignoreCase: Boolean = ...): Int defined in kotlin.text inline val <T:Number> T.sgn get() = if (this<0) -1 else 1 ^

¿Alguien podría ayudarme a entender por qué hay un desajuste de tipo y por qué kotlin.text importa aquí? ¿Existe un enfoque que podría utilizar para solucionar este problema y hacer que este getter de properties se aplique a todas las subclasss de Number? (Una vez más, sé que este no es un caso de uso significativo, sino más bien un ejemplo simplificado que me ayuda a comprender los principios que lo explican). Gracias de antemano por cualquier consejo que alguien pueda dar …

Su primera function funciona porque Int implementa Comparable<Int> , eso es a lo que se traduce el operador < . Sin embargo, si observas la class Number , verás que solo tiene funciones para las conversiones a sus diversas subclasss; no implementa Comparable , por lo tanto, no puedes usar el operador < en ella.

Lo que podría hacer en su lugar es convertir su Number a un Double primero, y luego ver si es negativo:

 inline val <T : Number> T.sgn get() = if (this.toDouble() < 0) -1 else 1 

También podría hacer que su código original (con o sin generics) funcione implementando la function compareTo para Number como una extensión:

 operator fun Number.compareTo(other: Number) = this.toDouble().compareTo(other.toDouble()) 

Solo ten en count que lanzar todo a Double puede resultar en perder precisión.

  • Kotlin: Cómo extender la class enum con una function de extensión
  • Android Studio y Kotlin: reference no resuelta: también
  • ¿Los methods de extensión y las properties de extensión son malas prácticas?
  • Comtesting si mi actividad está en MultiWindowMode o no está usando Kotlin
  • Propiedad de extensión en línea Kotlin
  • Funciones de extensión Kotlin por tipo
  • La function de extensión no crea un nuevo object Observable
  • Usa la extensión Kotlin en la class java de Android
  • ¿Cómo colocar una extensión de Kotlin en un file de class?
  • Acceso a la function de extensión de Kotlin Campo privado de Java
  • El resultado es el mismo, pero el caso de testing no pasa en la testing unitaria