如何扩展Kotlin Number类或使用泛型来创建一个简单的属性getter,它将在所有的Nu​​mber子类上运行?

我想通过构建非常简单的方法和扩展内置类的属性获取器来了解Kotlin抽象类扩展和泛型的更多信息。 我主要是成功的,但是我被数字类难住了。 我的测试属性Number.sgn旨在返回Number的任何子类的符号(1或-1作为Int)。 为了简单起见,负数应该返回-1,而正数和0应该返回1.我对这个方法的用例不是特别感兴趣,但是为了理解如何写这样简单的东西 – 以及为什么我的代码生成错误它。 我的模块中唯一的导入是kotlin.text.*并且我收到的错误消息确实指向那里的冲突。 我只是不明白为什么它会发生冲突,以及如何克服它 – 虽然我猜这是一个新手的错误。

我首先写了代码来扩展Int类,它工作正常:

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

然后,我试图将其推广到Number类,如下所示:

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

编译错误如下:

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 ^

然后,我尝试了一种不同的方法,使用泛型:

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

而我从编译器收到同样的错误:

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 ^

谁能帮我理解为什么有一个类型不匹配,为什么kotlin.text在这里重要? 有没有一种方法可以用来解决这个问题,并让这个属性getter应用于Number的所有子类? (再次,我知道这不是一个有意义的用例,而是一个简化的例子,以帮助我理解背后的原则。)预先感谢任何人的建议可以给…

你的第一个函数可以工作,因为Int实现了Comparable<Int> ,这就是<运算符被转换成的内容。 然而,如果你看一下Number类,你会发现它只有函数用于转换到它的各个子类 – 它没有实现Comparable ,因此,你不能使用它的<运算符。

你可以做的是将你的Number转换为Double ,然后看看它是否为负数:

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

您还可以通过将NumbercompareTo函数作为扩展来使您的原始代码(带或不带泛型)工作:

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

请注意,将所有东西都转换为Double可能会导致精度下降。