it is suggested to use interfaces for `Property` ...
# community-support
c
it is suggested to use interfaces for
Property
"holders/extensions" (from what I can tell). is there a good way to use
finalizeOnRead
with those? as if you need a value and don't get it, setting it later won't work.
v
If you want to do that when creating the holder / extension always, then use an abstract class and do it in the constructor / init. Alternatively, do it where you register / create it, just like how you should set convention values there to have the extension as opinion-free as possible. Having then as interface is simply the least-boilerplate way to define them if you do not need concrete code in them.
c
right, yeah, it'd be nice if it also returned
this
so you can't "builder" them in place. I digress
if I need to ... access
ValueSourceParameters
(and I'm making some other assumptions here). can I have an interface that extends the
ValueSourceParameters
but the abstract is injected? the assumption is that if I register the
ValueSourceParameters
as an extension then it'll be available if I apply the generic to the
ValueSource
.
Copy code
abstract class HeadBranchValueSource implements ValueSource<String, GitConfigurationExtension> {
v
I'm neither sure what you mean by "but the abstract is injected", nor by "it'll be available if I apply the generic to".
c
well if
GitConfigurationExtension
is an interface, and there's an
AbstractGitConfigurationExtension
would
HeadBranchValueSource::getParameters
return the instance of
AbstractGitConfigurationExtension
? or would it just go about creating its own implementation
t
There's no way to tell Gradle about
AbstractGitConfigurationExtension
other than by using it in the ValueSource generics.
BTW, are you sure you need to call
finalizeValueOnRead
? Most of the time, IIRC, the property will be finalized by Gradle at some point anyway, and for parameters of a ValueSource, that would be just before the ValueSource is created, just after you configured them on the ValueSourceSpec.
v
As Thomas said regarding the abstract class. Otherwise Gradle would also have a problem of there are multiple subclasses. Only where your create things explicitly, or on some domain collections you can provide a public interface and an actual implementation class
c
for parameters of a ValueSource, that would be just before the ValueSource is created,
interpretation, just before "new" is called which is... awful and not lazy. should be just before
obtain
is called...
or really finalizeOnRead should just be the default
but I know why they do this. DI failure... because the getParameters() method could be called in the constructor
although even then if they were just auto finalizeOnRead that wouldn't matter
t
new
? Value sources are created by
providers.of()
c
And you think that no constructor is ever called? That nothing ever calls constructor
t
Looks like I might have misinterpreted your message. Yes, it appears like that would be just before Gradle instantiates your value source.
v
No, it is not at all
I just tried.
Copy code
abstract class MyValueSource : ValueSource<String, MyValueSource.Parameters> {
    override fun obtain(): String {
        println(parameters.param.get())
        parameters.param.set("bar")
        println(parameters.param.get())
        return ""
    }

    interface Parameters : ValueSourceParameters {
        val param: Property<String>
    }
}
providers.of(MyValueSource::class) {
    parameters.param.set("foo")
}.get()
works fine and prints first
foo
then
bar
, so even within
obtain
you can still change the property.