https://kotlinlang.org logo
#getting-started
Title
# getting-started
h

hfhbd

07/01/2022, 7:15 AM
If you use a ReadWriteProperty with the by operator, is there any possibility to access the underlying delegate? Ideally, I want to override the toString method but keep using idiomatic code
Copy code
fun main() {
    var s: String by Print {
        "$this$this"
    }
    s = "foo"
    println(s)
}

class Print<T : Any>(private val format: T.() -> String) : ReadWriteProperty<Nothing?, T> {
    constructor(initial: T, formatter: T.() -> String) : this(formatter) {
        value = initial
    }

    private lateinit var value: T

    override fun getValue(thisRef: Nothing?, property: KProperty<*>): T = value

    override fun setValue(thisRef: Nothing?, property: KProperty<*>, value: T) {
        this.value = value
    }

    override fun toString(): String = value.format()
}
j

Joffrey

07/01/2022, 7:18 AM
The door for a more idiomatic solution will be open by the "explicit backing fields" feature (the prototype is already out). In the meantime, you can declare the delegate in a separate variable, and use that variable in the
by
clause
But I'm not sure I understand your goal here. Do you want the
toString
of the property
s
to be overridden by that of the delegate?
👌 1
h

hfhbd

07/01/2022, 7:21 AM
Yeah, I am aware of using another delegate variable:
Copy code
val sPrint = Print<String> { "$this$this" }
var s: String by sPrint
s = "foo"
println(sPrint)
println(s) // oops
But you could print the wrong variable
The explicit backing field alternative should interesting. I will take a look
j

Joffrey

07/01/2022, 7:58 AM
I mean the backing field feature will not help with your goal here then. One use case is to help access the property delegate, but it won't change the fact that the value itself has a different
toString
from the delegate
The delegate is technically just a way to provide the value. After that, the value is like any other value. What you could do is make the delegate return a wrapper of your value with a different
toString()
, but that is not possible for every type, because you would need to return a custom subtype of the property type
h

hfhbd

07/01/2022, 10:17 AM
Yeah, I noticed it too 😄 It is not possible because type of the variable would be
Print<String>
, ideally I want to have
String
. I think, I will use the first approach: Use a separate delegate variable and a custom detekt rule to prevent printing the primitive variable without the formatter.
j

Joffrey

07/01/2022, 10:22 AM
It doesn't look like delegation is useful here to be frank, because nothing happens to
s
. You're just creating something on the side, so it should look like this - something on the side. For instance, something as simple as:
Copy code
var s: String = "foo"
val formattedS: String get() = "$s$s"
h

hfhbd

07/01/2022, 10:26 AM
In this simple example it is true. But the delegate should do more than only formatting 🙂
👌 1
4 Views