Доступ к делегирующему получателю с делегацией в Котлине - PullRequest
0 голосов
/ 17 апреля 2019

Учитывая интерфейс:

interface Countable
{
    val count: Int
}

И реализация / фабрика:

fun countable(counter: () -> Int): Countable = object : Countable
{
    override val count: Int
        get() = counter()
}

Я могу реализовать это с помощью функции делегирования класса by:

class CountableThing : Countable by countable({ 123 })

Так что этот фрагмент предсказуемо выводит 123:

fun main()
{
    val countableThing = CountableThing()
    println(countableThing.count)
}

Мой вопрос, в контексте класса делегата, есть ли способ получить экземпляр делегирующего получателя?

Другими словами, может ли моя реализация делегата Countable (анонимный объект, определенный в fun countable) увидеть / получить доступ к экземпляру приемника класса CountableThing?

Я пробовал это:

fun <T> countable(receiver: T, counter: () -> Int): Countable = object : Countable
{
    // ...
}

class CountableThing : Countable by countable<CountableThing>(this, { 123 })

Но это недействительно, потому что ожидаемо:

class CountableThing : Countable by countable<CountableThing>(this, { 123 })
                                                             /^^^^
                        'this' is not defined in this context

1 Ответ

2 голосов
/ 18 апреля 2019

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

class Example {
    var p: String by Delegate()
}

class Delegate {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return "$thisRef, thank you for delegating '${property.name}' to me!"
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("$value has been assigned to '${property.name}' in $thisRef.")
    }
}

, тогда вы можете использовать

val e = Example()
println(e.p)

, которая печатает:

Example@33a17727, thank you for delegating ‘p’ to me!

Как вы можете видеть, в вашей реализации делегата вы можете использовать thisRef, который является ссылкой на объект, свойство которого было делегировано.

...