我如何扩展 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
可能会导致精度下降。
我正在尝试通过构建非常简单的方法和扩展内置 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
可能会导致精度下降。