Falló la inferencia de tipo: no hay suficiente información para inferir el parámetro. Especifíquelo explícitamente.

Intento escribir una aplicación Vaadin en Kotlin. Para el data binding, Vaadin 8 ahora ofrece la posibilidad de un data binding seguro. En Kotlin, esperaba un trabajo así:

class LoginModel { var username: String = "" var password: String = "" } class LoginView : FormLayout() { val name = TextField("name") val password = TextField("password") val loginButton = Button("login") init { val binder = Binder<LoginModel>() binder.forField(name).bind( { it.username }, { bean, value -> bean.username = value }) //... } } 

Recibo el siguiente post de error aquí:

 Error:(23, 31) Kotlin: Type inference failed: Not enough information to infer parameter BEAN in fun <BEAN : Any!, TARGET : Any!, BEAN : Any!> Binder.BindingBuilder<BEAN#1 (type parameter of bind), TARGET>.bind(p0: ((BEAN#1!) -> TARGET!)!, p1: ((BEAN#1!, TARGET!) -> Unit)!): Binder.Binding<BEAN#1!, TARGET!>! Please specify it explicitly. 

Intenté explícitamente especificando los parameters de tipo:

 binder.forField(name).bind<LoginView, String, LoginView>( { it.username }, { bean, value -> bean.username = value }) 

pero eso lleva al post de error (y a otros errores de syntax, por lo que no seguí ese enfoque)

 Error:(23, 35) Kotlin: No type arguments expected for fun bind(p0: ValueProvider<LoginModel!, String!>!, p1: Setter<LoginModel!, String!>!): Binder.Binding<LoginModel!, String!>! defined in com.vaadin.data.Binder.BindingBuilder 

Mi segundo enfoque fue tratar de pasar los descriptores de acceso de propiedad de Kotlin directamente, pero el post de error fue el mismo que el primero:

 binder.forField(name).bind(LoginModel::username.getter, LoginModel::username.setter) 

El último bash fue intentar usar un método de extensión y hacer que todo sea lo más explícito posible:

 fun <BEAN, TARGET> Binder.BindingBuilder<BEAN, TARGET>.bind(property: KMutableProperty1<BEAN, TARGET>) { fun set(bean: BEAN): TARGET = property.get(bean) fun get(bean: BEAN, value: TARGET): Unit = property.set(bean, value) this.bind(::set, ::get) } 

Pero todavía conduce al mismo post de error que el primero

    He intentado con tu ejemplo y comstack muy bien con mi Intellij 2017.1.4 y Kotlin 1.1.2-5. ¿Probablemente has descubierto un error en la versión anterior de un plugin de Kotlin?

    El bind método no toma parameters generics por lo que no puede ser genérico. El método forField toma un parámetro genérico, entonces quizás puedas probar

      binder.forField<String>(name).bind( { it.username }, { bean, value -> bean.username = value }) 

    Pero primero, asegúrese de tener la versión más nueva del complemento de Kotlin y / o quizás probarlo con Intellij Community Edition.

    Sin embargo, le pido que use bind(String) ya que otros methods de vinculación no funcionarán con las validaciones de JSR303. También puedes definir el siguiente método de extensión:

     fun <BEAN, FIELDVALUE> Binder.BindingBuilder<BEAN, FIELDVALUE>.bind(prop: KMutableProperty1<BEAN, FIELDVALUE?>): Binder.Binding<BEAN, FIELDVALUE> = bind(prop.name) 

    Y llámalo de la siguiente manera desde tu código binder.forField(name).bind(LoginModel::username) . Por favor, mira aquí para más ejemplos: https://github.com/mvysny/karibu-dsl/blob/master/example-v8/src/main/kotlin/com/github/vok/karibudsl/example/form/FormView.kt

    Dado que su model es bastante simple, puede completar el enlace conectándose a la propiedad con el nombre dado a través del método Binder#bind(String propertyName)

     val binder = Binder<LoginModel>() binder.forField(name).bind("username"); 

    Debe usar el nivel de API 26+. Esta versión ha cambiado la firma de View.findViewById () – ver aquí https://developer.android.com/preview/api-overview.html#fvbi-signature

    El resultado de findViewById es ambiguo, debe proporcionar el tipo:

    Por ejemplo:

     val myTextView = findViewById(R.id.list) as TextView 

    se convierte

     val myTextView = findViewById<TextView>(R.id.myTextView)