elect
10/02/2021, 10:40 AMval username by Input { }
Where
class Input {
companion object {
operator fun invoke(..): Input {
..
}
}
}
And
internal operator fun Any.getValue(thisRef: Any?, property: KProperty<*>): Input {
println("$thisRef, thank you for delegating '${property.name}' to me!")
val pInput = property as KProperty0<Input>
println(pInput)
return pInput.get()
}
pInput is a valid KProperty0 class, but the moment I call .get() to retrieve Input, then I get:
java.lang.UnsupportedOperationException: call/callBy are not supported for this declaration.Why? How can I fix it? What is the way to retrieve the
Input instance produced by its own companion object?Joffrey
10/02/2021, 10:51 AMinvoke on the companion instead of just using a constructor?Joffrey
10/02/2021, 10:53 AMgetValue declared here? Inside the Input class or at the top level?elect
10/02/2021, 10:53 AMelect
10/02/2021, 10:55 AMInputJoffrey
10/02/2021, 10:55 AMAny ?elect
10/02/2021, 10:56 AMusername ) as well and use it to create Input (it's one of the fields)Joffrey
10/02/2021, 10:58 AMusername so the delegate is the one that's supposed to provide the valueJoffrey
10/02/2021, 10:59 AMelect
10/02/2021, 11:00 AMelect
10/02/2021, 11:00 AMclass Input {
fun getValue(..)
}
?elect
10/02/2021, 11:00 AMinvoke ) is actually providing the value, or am I wrong?elect
10/02/2021, 11:03 AMAny so that I can also have type inferenceJoffrey
10/02/2021, 11:51 AMInput to be the type of the delegate but you also want it to be the type of the value? I cannot really suggest anything at the moment because I didn't get what you're trying to do. What is the purpose of the delegate?elect
10/02/2021, 11:54 AMusername: Input in the lambda, this should include saving the variable name itself, that is username inside the Input instance itselfelect
10/02/2021, 11:56 AMval task by tasks.creating { }Joffrey
10/02/2021, 12:06 PMval username = Input { ... }elect
10/02/2021, 12:07 PMusername from inside Input{..} in that wayelect
10/02/2021, 12:08 PMusername is Input.idelect
10/02/2021, 12:13 PMclass Delegate(val block: Input.() -> Unit) {
operator fun getValue(thisRef: Any?, property: KProperty<*>): Input {
println("$thisRef, thank you for delegating '${property.name}' to me!")
return Input().apply {
block()
id = property.name
}
}
}Joffrey
10/02/2021, 12:15 PMInput type. The code you provided last can work, but then you'll create a new instance of Input every time you access username. You can use the provideDelegate approach in order to store the value and return the same one everytime it's accessedelect
10/02/2021, 12:17 PMelect
10/02/2021, 12:17 PMprovideDelegate approach?elect
10/02/2021, 12:19 PMJoffrey
10/02/2021, 12:20 PMprovideDelegate function is called once when the class containing the delegated property is initialized. This function creates an instance of the delegate class and you already have access to the property name when doing so, so you can store the value in the delegate instance itselfJoffrey
10/02/2021, 12:45 PMJoffrey
10/02/2021, 12:47 PMelect
10/02/2021, 4:44 PMelect
10/02/2021, 4:44 PMby won't save the value in the variable by default, like by lazy, instead of requiring all this boilerplate code, but anywayelect
10/02/2021, 4:52 PMOne of the possible use cases ofis to check the consistency of the property upon its initialization.provideDelegate
elect
10/02/2021, 5:04 PMelect
10/02/2021, 5:06 PMPropertyDelegateProvider
(at the end of the same doc link posted above)
I guess no, because there isn't a way to pass the lambdaJoffrey
10/02/2021, 6:23 PMPropertyDelegateProvider and never thought of using SAM conversions like this!
It is definitely possible to use by capturing the configure lambda (and it would simplify the whole thing quite a bit):
private fun Input(configure: Input.() -> Unit) = PropertyDelegateProvider { thisRef: Any?, prop ->
val input = Input(prop.name).apply { configure() }
ReadOnlyProperty<Any?, Input> { _, _ -> input }
}
So the whole thing is now: https://pl.kotl.in/n6KFhfDOp
Thanks for making me learn this 🙂Joffrey
10/02/2021, 6:38 PMI still don't get why a planI don't get your point here. The implementation of the lazy delegate does need to store thewon't save the value in the variable by default, likebyby lazy
value explicitly, look:
https://github.com/JetBrains/kotlin/blob/master/libraries/stdlib/src/kotlin/util/Lazy.kt#L95
However, they don't need the additional indirection of provideDelegate because they don't need information about the property itself (like the name of the property), unlike in your use case.elect
10/02/2021, 6:47 PM