I'm using kind of dynamic form system coming from the backend. To be able to map my form I have a visitor pattern with generics, I have it working in Java but I can't make it to work in Kotlin.
I have this interface:
internal interface FormFieldAccessor<T> {
fun getFormField(formFieldDefinition: FormFieldDefinition): FormField<T>
fun setValueToBuilder(builder: Builder, value: T)
fun accept(visitor: FormFieldVisitor)
fun getValue(personalInfo: PersonalInfo): T
}
Then I have my list of accessors like this:
val accessors = mutableMapOf<String, FormFieldAccessor<*>>()
accessors[FIRST_NAME] = object : FormFieldAccessor<String> {
override fun getValue(personalInfo: PersonalInfo): String {
return personalInfo.surname
}
override fun accept(visitor: FormFieldVisitor) {
visitor.visitString(this)
}
override fun getFormField(formFieldDefinition: FormFieldDefinition): FormField<String> {
//not relevant
}
override fun setValueToBuilder(builder: Builder, value: String) {
builder.withSurname(value)
}
}
//more other accessors with different type like Int or Boolean
And want to use it like this:
accessors[FIRST_NAME]!!.setValueToBuilder(builder, field.value )
But this is not working and give me:
Out-projected type 'FormFieldAccessor<*>' prohibits the use of 'public abstract fun setValueToBuilder(builder: Builder, value: T): Unit defined in FormFieldAccessor'
If you have an idea of what I'm doing wrong would be cool :)
EDIT: here is a smaller gist of the structure I have https://gist.github.com/jaumard/1fd1ccc9db0374cb5d08f047414a6bc8
I don't want to loose the type by using Any, feel frustrated compare to Java as it's really easy to implement. I understand the problem with the star projection now but is there anything else than this to achieve the same as in java ?