Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a Kotlin Comparable Type?

Tags:

Just learning to define a DateRange type

val wholeYear2017 = Date(2017,1,1)..Date(2017,12,31)

So I created the type as below

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)
}

But I got a compile error

One type of argument expected for class DateRange<Date: Comparable<Date>> : ClosedRange<Date>

What did I missed? Did I do it correctly?

like image 332
Elye Avatar asked Sep 29 '17 08:09

Elye


People also ask

How do you implement a comparable interface in Kotlin?

Since Kotlin provides the programmer, to define new types in terms of classes, there must be a way to compare the instances of these classes. As in Java, the Comparable interface provides a compareTo() function to compare two objects. Kotlin provides this through the Comparable interface.

How do you use kotlin compareTo?

Using the compareTo() function to compare Kotlin strings While the previous methods return a boolean value ( true or false ), compareTo() returns an integer: Returns 0 if the main string and the other string are equal. Returns a negative number if the other string's ASCII value is bigger than the main string.

What is with keyword in Kotlin?

It turns out the Kotlin in keyword is shorthand for the operator contains . It's not an interface or a type, just the operator. If we wanted to make a custom type to check if a value is in our type, all we need to do is add the operator contains() . Let's look at an example.


1 Answers

Is your question really about how to create a Comparable type? Then just have your type implement the Comparable interface (override 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
    }
 }

You don't need a rangeTo method because all Comparable<T> types have a rangeTo extension already defined. See Ranges and rangeTo. But, if you still want your own DateRange type (for other purposes), the simpler form of the DateRange class would be...

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

In other words, there is no need for the generic parameter on DateRange.

Then you would write your own rangeTo operator. Either, add operator fun rangeTo to your Date class, or provide a root level extension function (my preference which is consistent with the Kotlin library approach). Both will shadow/hide the Comparable<T>.rangeTo extension function for your Date type.

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

// root level extension
operator fun Date.rangeTo(that: Date) = DateRange(this,that)
like image 56
Les Avatar answered Sep 20 '22 05:09

Les