我如何扩展 Kotlin Number class 或使用泛型来创建一个简单的 属性 getter 来对所有 Number subclass 进行操作?

How do I extend Kotlin Number class or use generics to create a simple property getter which will operate on all Number subclasses?

我正在尝试通过构建非常简单的方法和扩展内置 classes 的 属性 getters 来了解有关 Kotlin 抽象 class 扩展和泛型的更多信息.我基本上是成功的,但我被数字 class 难倒了。我的测试 属性 Number.sgn 旨在 return Number 的任何子 class 的符号(1 或 -1 作为 Int)。为简单起见,负数应该 return -1,而正数和 0 应该 return 1。我对这种方法的用例不是特别感兴趣,但为了了解如何编写像这样简单的东西-- 以及为什么我的代码会产生错误。我的模块中唯一的导入是 kotlin.text.* 并且我收到的错误消息确实提到了那里的冲突。我只是不明白为什么它会发生冲突以及如何克服它——尽管我猜这是一个新手错误。

我首先编写了扩展 Int class 的代码,效果很好:

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

然后我尝试概括并将其移动到数字 class,如下所示:

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 的所有子 classes? (同样,我知道这不是一个有意义的用例,而是一个帮助我理解其背后原理的简化示例。)提前感谢任何人可以提供的任何建议...

您的第一个函数之所以有效,是因为 Int implements Comparable<Int>, that's what the < operator is translated to. However, if you look at the Number class,您会发现它只有用于转换为各种子 classes 的函数 - 它没有实现Comparable,因此,您不能在其上使用 < 运算符。

您可以先将 Number 转换为 Double,然后查看它是否为负值:

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

您还可以通过为 Number 实现 compareTo 函数作为扩展来使您的原始代码(有或没有泛型)工作:

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

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