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?
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.
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.
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.
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With