Assume I have an interface that provides many immutable properties with default getters, as such
interface Repository {
val name : String
val pattern : String
get() = "foo/bar/baz"
var url : String
get() = "http://mycompanyrepo.com/$name"
fun add() {
TODO("do something interesting here")
}
}
Now, there are several concrete implementations that just use most of the defaults. However, I also want to provide a ConfigurableRepository
that allows for more flexibility in other projects that want to configure this at runtime, based on other user parameters.
How can I create a primary constructor that has optional parameters?
I was hoping something along the lines of:
class ConfigurableRepo(var name, var pattern, var url) {
...
}
Edited for clarification
The intent here is to use primary constructor behavior, where the named parameters are optional. More specifically, name
, pattern
, and url
are all optional to anyone calling the constructor, and it will default to the interface's getters. But, I'm obviously trying to force the Kotlin interface
to fit this model and it is probably a noob Kotlin user mistake, as I ultimately have no access to super here.
From the class docs
In fact, for declaring properties and initializing them from the primary constructor, Kotlin has a concise syntax:
class Person(val firstName: String, val lastName: String, var age: Int) {
// ...
}
I seem to be getting errors that this hides members of the supertype and requires the override
modifier. If I try to override the supertype and then provide a default, it complains that supertypes aren't accessible in this context.
Can this only be done in a secondary constructor with mutable values?
I'm also open to suggestions/feedback on better ways to provide an interface that supports configuration over convention. The most important aspect being that the interface always provide defaults for a convention. Or, more simply put:
Is there a better way?
url
asvar
? – Robert Jack Willvar
property must override both getter and setter or none of them. Otherwise it won't compile, because the compiler misses a backing field which an interface can't have. – Robert Jack Willset (u: String) {}
aftervar url
in yourinterface Repository
to get it compiling in Kotlin 1.2.31. And it think it makes sense that way, since interfaces never have fields, only abstract properties. (If you want fields, then an abstract class would be the way to go.) – Robert Jack Willvar
andval
. For properties the main difference betweenval
andvar
is that only the latter has a setter! Soval
should work in your case. (And it can be overridden as avar
by adding a setter.) – Robert Jack Will