如何制作Kotlin可比类型?

Ely*_*lye 10 kotlin

只是学习定义DateRange类型

val wholeYear2017 = Date(2017,1,1)..Date(2017,12,31)
Run Code Online (Sandbox Code Playgroud)

所以我创建了如下类型

class DateRange<Date: Comparable<Date>>(override val start: Date, override val endInclusive: Date)
    : ClosedRange<Date>

class Date (val year: Int, val month: Int, val day: Int) {

    operator fun compareTo(other: Date): Int {
        if (this.year > other.year) return 1
        if (this.year < other.year) return -1
        if (this.month > other.month) return 1
        if (this.month < other.month) return -1
        if (this.day > other.day) return 1
        if (this.day < other.day) return -1
        return 0
    }

    operator fun rangeTo(that: Date): DateRange = DateRange(this, that)
}
Run Code Online (Sandbox Code Playgroud)

但是我遇到了编译错误

One type of argument expected for class DateRange<Date: Comparable<Date>> : ClosedRange<Date>
Run Code Online (Sandbox Code Playgroud)

我错过了什么?我做得对吗?

Les*_*Les 12

您的问题真的是关于如何创建Comparable类型吗?然后让你的类型实现Comparable接口(覆盖compareTo).

class Date(val year: Int, val month: Int, val day: Int) : Comparable<Date> {
    override operator fun compareTo(other: Date): Int {
        if (this.year > other.year) return 1
        if (this.year < other.year) return -1
        if (this.month > other.month) return 1
        if (this.month < other.month) return -1
        if (this.day > other.day) return 1
        if (this.day < other.day) return -1
        return 0
    }
 }
Run Code Online (Sandbox Code Playgroud)

您不需要rangeTo方法,因为所有Comparable<T>类型都已rangeTo定义扩展.见范围范围.但是,如果你仍然想要自己的DateRange类型(用于其他目的),那么DateRange类的简单形式就是......

class DateRange(override val start: Date, override val endInclusive: Date)
    : ClosedRange<Date>
Run Code Online (Sandbox Code Playgroud)

换句话说,不需要通用参数DateRange.

然后你会编写自己的rangeTo运算符.要么添加operator fun rangeTo到您的Date类,要么提供根级别扩展功能(我的偏好与Kotlin库方法一致).两者都会Comparable<T>.rangeTo为您的Date类型隐藏/隐藏扩展功能.

// class level rangeTo operator
operator fun rangeTo(that: Date) = DateRange(this,that)

// root level extension
operator fun Date.rangeTo(that: Date) = DateRange(this,that)
Run Code Online (Sandbox Code Playgroud)


cub*_*l42 7

你需要实现Comparable接口.你可以使用compareValuesBy辅助函数:

data class Data(
        val a: Int,
        val b: Int
) : Comparable<Data> {
    override fun compareTo(other: Data) = compareValuesBy(this, other,
            { it.a },
            { it.b }
    )
}
Run Code Online (Sandbox Code Playgroud)

  • 这应该是公认的答案。迄今为止最优雅的解决方案! (7认同)