如何扩展KotlinNumber类或使用泛型来创建一个简单的属性getter,它将对所有Number子类进行操作?

bt1cpqcv  于 2023-04-07  发布在  Kotlin
关注(0)|答案(2)|浏览(140)

我试图通过构建非常简单的方法和扩展内置类的属性getter来学习更多关于Kotlin抽象类扩展和泛型的知识。我大部分都很成功,但我被Number类难倒了。我的测试属性Number.sgn旨在返回符号(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的所有子类?(再次,我知道这不是一个有意义的用例,而是一个简化的例子,以帮助我理解这背后的原则。)提前感谢任何人可以给予的任何建议。

cbeh67ev

cbeh67ev1#

你的第一个函数可以工作,因为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可能会导致精度损失。

sr4lhrrt

sr4lhrrt2#

你甚至可以用相同类型的结果来做。

inline val<T> T.sign where T: Number, T: Comparable<T> get() = run {
    if (this.toDouble() < 0) (-1 as T) else (1 as T)
}

内存中的更多优化-将源编号转换为字节:

inline val<T> T.sign where T: Number, T: Comparable<T> get() = with(this.toByte()) {
    if (this < 0) -1 as T else if (this > 0) 1 as T else 0 as T
}

相关问题