Функция расширения Котлина на непостоянном свойстве

Я пытаюсь установить функцию расширения для изменяемого свойства, чтобы я мог переназначить свойство в функции расширения. Я хотел знать, было ли это возможно.

Мои цели - сделать Date расширения для легкого доступа. Например:

fun Date.addDays(nrOfDays: Int): Date {
    val cal = Calendar.getInstance()
    cal.time = this
    cal.add(Calendar.DAY_OF_YEAR, nrOfDays)
    return cal.time
}

Эта функция добавляет количество дней к дате, используя Calendar объект. Проблема в том, что каждый раз мне приходится возвращать новую дату, которая может сбивать с толку, чтобы переназначать каждый раз, когда вы используете эту функцию.

Что я пробовал:

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

К сожалению, это не может быть использовано на Date объект.

Можно ли сделать это?

2 ответа

Решение

К сожалению, вы не можете определить расширение для свойства члена и свободно вызывать его в Kotlin 1.0.3.

Ваше расширение может быть переписано для работы следующим образом:

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

со следующим использованием:

class C(var date: Date) { ... }
val c = C(someDate())

C::date.addDays(c, 123)

Со связанными вызываемыми ссылками (вероятно, поддерживается в Kotlin 1.1) это будет возможно со следующим синтаксисом:

c::date.addDays(123)

Как подсказывает @MarcinKoziński, вы также можете изменять свои Date объекты без переназначения объекта:

fun Date.addDays(nrOfDays: Int) {
    val cal = Calendar.getInstance()
    cal.time = this
    cal.add(Calendar.DAY_OF_YEAR, nrOfDays)
    this.time = cal.timeInMillis
}

с использованием:

class C(var date: Date)
val c = C(someDate())

c.date.addDays(123)

С этим решением вы должны контролировать ссылки на Date объект, который мутировал. Это решение хорошо работает с изменяемыми объектами, хотя оно не подходит для свойств, хранящих неизменяемые объекты.

Вместо возвращения нового Date и пытаясь обновить вашу собственность, вы можете просто изменить Date что ваша собственность уже имеет:

fun Date.addDays(nrOfDays: Int) {
    val cal = Calendar.getInstance()
    cal.time = this
    cal.add(Calendar.DAY_OF_YEAR, nrOfDays)
    this.time = cal.timeInMillis
}
Другие вопросы по тегам