类型推断失败:没有足够的信息来推断参数请明确指定

我正在尝试在Kotlin上写一个Vaadin应用程序。 对于数据绑定,Vaadin 8现在提供了类型安全数据绑定的可能性。 在科特林,我会期待这样的工作:

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 }) //... } } 

我在这里收到以下错误消息:

 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. 

我尝试通过明确指定类型参数:

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

但是这导致错误信息(和其他sytax错误,所以我没有按照这种方法)

 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 

我的第二种方法是直接尝试传递Kotlin属性访问器,但错误消息与第一个相同:

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

最后的批准是试图使用扩展方法,并尽可能明确地做一切事情:

 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) } 

但它仍然导致与第一个相同的错误信息

我已经尝试过你的例子,它和我的Intellij 2017.1.4和Kotlin 1.1.2-5编译得很好。 大概你已经发现了一个老版本的Kotlin插件的bug?

该方法bind没有通用参数,所以不能被基因化。 forField方法需要一个通用参数,所以也许你可以试试

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

但首先,请确保您拥有Kotlin插件的最新版本,或者也可以使用Intellij Community Edition进行试用。

不过,我强烈建议你使用bind(String)因为其他绑定方法不能用于JSR303验证。 你也可以定义下面的扩展方法:

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

并从代码binder.forField(name).bind(LoginModel::username)如下调用它。 请看这里更多的例子: https : //github.com/mvysny/karibu-dsl/blob/master/example-v8/src/main/kotlin/com/github/vok/karibudsl/example/form/FormView.kt

由于您的模型非常简单,您可以通过使用Binder#bind(String propertyName)方法连接具有给定名称的属性来完成绑定

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

您必须使用API​​级别26+。 这个版本改变了View.findViewById()的签名 – 请参阅https://developer.android.com/preview/api-overview.html#fvbi-signature

findViewById的结果是不明确的,你需要提供类型:

例如:

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

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