我刚刚实施了选择排序,以熟悉Kotlin并碰到一个未经检查的演员,我发现很难摆脱。实现基于kotlin.Comparable
接口:
object SelectionSort {
fun <T> sort(a: Array<Comparable<T>>) {
val N = a.size
for(i in 0..N - 2) {
var min = i
for(j in i + 1..N - 1) {
if(less(a[j], a[min])) {
min = j
}
}
exchange(a, i, min)
}
}
private fun <T> exchange(a: Array<Comparable<T>>, i: Int, min: Int) {
val temp = a[i]
a[i] = a[min]
a[min] = temp
}
private fun <T> less(comparable: Comparable<T>, comparable1: Comparable<T>): Boolean {
return comparable < (comparable1 as T) // Here is the unchecked cast
}
}
确切的消息是&#34; 未选中广告:Comparable<T>
到T
&#34;。
我的偏好是使用kotlin.Comparable
接口作为sort
方法的主要参数以及辅助方法。但是如何以干净的方式比较一个与另一个相似的仿制药呢?
如果这是不可能的,那么使用接口实现诸如选择排序之类的东西会有什么干净的选择呢?
基于此answer,我重新编写了我的选择排序实现:
object SelectionSort {
fun <T : Comparable<T>> sort(a: Array<T>) {
val N = a.size
for (i in 0..N - 2) {
var min = i
for (j in i + 1..N - 1) {
if (less(a[j], a[min])) {
min = j
}
}
exchange(a, i, min)
}
}
fun <T> exchange(a: Array<T>, i: Int, min: Int) {
val temp = a[i]
a[i] = a[min]
a[min] = temp
}
fun <T : Comparable<T>> less(c1: T, c2: T) =
c1 < c2
}
此实施现在没有警告。
答案 0 :(得分:2)
您应该在<T : Comparable<T>>
和sort
上使用绑定less
。
fun <T : Comparable<T>> sort(arr: Array<T>) = ...
fun <T : Comparable<T>> less(l: T, r: T) = ...
如果没有合理的类型,没有理由采用具体的类型。
此外,sort
的参数不应为 Array<Comparable<T>>
。 Kotlin中的数组不变:如果A extends B
,则Array<A>
不是Array<B>
的子类型。这与Java不同,其中数组是协变的,String[]
是Object[]
的子类型。不变性是正确的方法。如果您现在定义排序,则无法编写
val arr: Array<String> = ...
sort(arr);
因为sort
需要Array<Comparable<String>>
,但arr
是Array<String>
。
此外,没有理由在exchange
fun <T> exchange(arr: Array<T>, i: Int, j: Int) = ...
答案 1 :(得分:1)
这解决了您的问题:
inline fun <reified T> less(c1: Comparable<T>, c2: Comparable<T>) =
if (c2 is T) {
c1 < c2
} else {
throw IllegalStateException() // whatever
}
如果您首先检查其类型T
,则无需强制转换。如果T
成为reified,则可以这样做,即您可以在运行时访问它(默认情况下,泛型类型在运行时不可用)。只有当您method
为inline
时,才能再次执行此操作。
请注意,在类型检查之后访问c2
可以而无需显式转换,因为编译器已经知道您正在做安全的事情,这称为"Smart Cast"。
如您所见,此实现在错误处理方面并非100%正确 - 但这取决于您; - )
但是:不要这样做。
我建议您在实现中摆脱Comparable
处理,以便sort
方法看起来像这样:
fun <T: Comparable<T>> sort(a: Array<T>)
这确保只能对实现T
的{{1}}进行排序,Comparable
在泛型类型中用:
(上限)表示。然后您的less
方法如下:
private fun <T : Comparable<T>> less(comparable: T, comparable1: T): Boolean {
return comparable < comparable1
}
无需演员: - )
(同样适用于exchange
)