Reputation: 9814
I'm trying to set an extension function on a mutable property so I can reassign the property in the extension function. I wanted to know if it was possible.
My goals is to make Date
extensions for easy access. For example:
fun Date.addDays(nrOfDays: Int): Date {
val cal = Calendar.getInstance()
cal.time = this
cal.add(Calendar.DAY_OF_YEAR, nrOfDays)
return cal.time
}
This function adds number of days to a date using a Calendar
object. The problem is each time I have to return a new date which can be confusing to reassign each time you use this function.
What I've tried:
fun KMutableProperty0<Date>.addDays(nrOfDays: Int) {
val cal = Calendar.getInstance()
cal.time = this.get()
cal.add(Calendar.DAY_OF_YEAR, nrOfDays)
this.set(cal.time)
}
Unfortunately this can't be used on a Date
object.
Is it possible to do this?
Upvotes: 3
Views: 1153
Reputation: 148089
Unfortunately, you cannot define an extension on a member property and call it fluently in Kotlin 1.0.3.
Your extension can be rewritten to work like this:
fun <T> KMutableProperty1<T, Date>.addDays(receiver: T, nrOfDays: Int) {
val cal = Calendar.getInstance()
cal.time = this.get(receiver)
cal.add(Calendar.DAY_OF_YEAR, nrOfDays)
this.set(receiver, cal.time)
}
with the following usage:
class C(var date: Date) { ... }
val c = C(someDate())
C::date.addDays(c, 123)
With bound callable references (likely supported in Kotlin 1.1) this will be possible with the following syntax:
c::date.addDays(123)
As @MarcinKoziński suggests, you can also mutate your Date
objects without reassigning the property:
fun Date.addDays(nrOfDays: Int) {
val cal = Calendar.getInstance()
cal.time = this
cal.add(Calendar.DAY_OF_YEAR, nrOfDays)
this.time = cal.timeInMillis
}
with usage:
class C(var date: Date)
val c = C(someDate())
c.date.addDays(123)
With this solution, you have to control the references to the Date
object which is mutated. This solution works good with mutable objects, though it is not suitable for a property storing immutable ones.
Upvotes: 1
Reputation: 11064
Instead of returning a new Date
and trying to update your property, you can just mutate the Date
that your property already holds:
fun Date.addDays(nrOfDays: Int) {
val cal = Calendar.getInstance()
cal.time = this
cal.add(Calendar.DAY_OF_YEAR, nrOfDays)
this.time = cal.timeInMillis
}
Upvotes: 3