我正在Kotlin中实现Quicksort算法。为此,我使用类型参数和单个函数 sort 创建了一个接口 ISort 。对于排序,我需要交换操作。我想知道这个交换功能的最佳位置是什么。我的想法:
1)不幸的是,在Kotlin中,无法保护接口功能。因此,每个类都可以看到它的实现中的交换,这不太好(虽然它也不是太糟糕,我同意)。
2)将它放入QuickSort实现更糟糕,因为可能有几个需要交换功能的ISort接口实现。
3)我的下一个想法是创建一个单例对象,但Kotlin允许具有类型参数的对象。
这是界面定义:
interface ISort<T> {
fun sort(toSort: MutableList<T>): MutableList<T>
// 1) Putting swap here has a too high visibility
}
这是QuickSort类的骨架:
class QuickSort<T> : ISort<T> {
override fun sort(toSort: MutableList<T>): MutableList<T> {
doQuickSort(toSort) // Internally uses swap
return toSort
}
// 2) Putting swap here might lead to code duplication of swap
}
因此,从软件工程的角度来看,什么是交换操作的最佳位置/位置。
答案 0 :(得分:1)
在档案sort.kt
左右,
package abc.def.sort
fun <T> quicksort(list: MutableList<T>): MutableList<T> {
...
}
// invisible in other files, but visibie in "sort.kt"
private fun <T> swap(...) {
...
}
要在其他类别中使用swap
函数,您需要在同一文件中定义其他排序函数。 (或多次复制swap
功能。)
这推荐用于非常简单的功能。
这类似于上面的方法,但比前一个方法更多OOP-ish。
object QuickSort {
fun <T> sort(list: MutableList<T>): MutableList<T> {
...
}
private fun <T> swap(...) {
...
}
}
或
object Sorts {
fun <T> quicksort(list: MutableList<T>): MutableList<T> {
...
}
// add other sort methods...
private fun <T> swap(...) {
...
}
}
但是,Kotlin(Best practices for top-level declarations)不建议这样做。
swap
函数可以通过这种方式重复用于其他类别。
abstract class Sort {
abstract fun <T> sort(list: MutableList<T>): MutableList<T>
protected fun <T> swap(...) {
...
}
}
object QuickSort : Sort() {
override fun <T> sort(list: MutableList<T>): MutableList<T> {
...
}
}
我认为[使类型参数T
成为类类型参数,而不是函数类型参数]会使问题变得更加复杂,因为每次使用不同类型时都必须创建一个类实例T
。