【问题标题】:How does Kotlin property access syntax work for Java classes (i.e. EditText setText)?Kotlin 属性访问语法如何适用于 Java 类(即 EditText setText)?
【发布时间】:2016-09-19 08:03:10
【问题描述】:

我正在尝试将我的 Android 项目切换到 Kotlin。我有一个EditTextTextView 的子类),我想以编程方式为其设置提示和文本。提示按预期工作。但是,对于文本,如果我尝试使用 Kotlin setter 语法进行操作,则会出现类型不匹配异常:

    val test = EditText(context)

    test.setHint("hint")    // Lint message: "Use property access syntax"
    test.hint = "hint"      // ok

    test.setText("text")    // ok (no lint message)
    test.text = "text"      // Type mismatch: inferred type is kotlin.String but android.text.Editable! was expected

如果我们查看声明,我们会发现继承自 TextView 的相同签名:

    public final void setHint(CharSequence hint)

    public final void setText(CharSequence text)

我的印象是x.y = zx.setY(z) 的快捷方式,但显然这种印象是错误的。 setText() 被视为普通方法而不是 setter,但是这两种方法之间有什么区别使编译器表现不同呢?我唯一能想到的是TextView 有一个mHint 属性,但我认为可能不是这样。

还有一点我不太明白,android.text.Editable 是从哪里来的?没有对应的setText(Editable)方法,也没有这种类型的公共字段。

【问题讨论】:

    标签: android android-edittext kotlin


    【解决方案1】:

    在为 Java getter/setter 对生成合成属性时,Kotlin 首先查找 getter。 getter 足以创建具有 getter 类型的合成属性。另一方面,如果只有 setter 存在,则不会创建该属性。

    当 setter 出现时,属性创建变得更加困难。原因是 getter 和 setter 可能有不同的类型。此外,getter 和/或 setter 可以在子类中被覆盖。

    在您的情况下,TextView 类包含一个 getter CharSequence getText() 和一个 setter void setText(CharSequence)。如果你有一个TextView 类型的变量,你的代码就可以正常工作。但是你有一个EditText 类型的变量。而EditText 类包含一个重写的getter Editable getText(),这意味着您可以为EditText 获取Editable,并将Editable 设置为EditText。因此,Kotlin 合理地创建了 Editable 类型的合成属性 textString 类不是 Editable,这就是为什么您不能将 String 实例分配给 EditText 类的 text 属性。

    【讨论】:

    • 很好的解释,先生。
    • 从 Kotlin 调用 java 时,我会说 linter 并没有真正帮助你,建议你使用综合属性。 1)当你可以使用它时一点也不明显(如 OP 的示例所示) 2)因为有时你可以使用它,有时你不能使用它,你最终会得到两种不同的编码风格,用于相似的外观操作 3)文档是在 Java 表示法中。我只是关闭了检查。
    • 那么如何从接口回调中获取文本。我想将对话框选择的文本设置为edittext。
    【解决方案2】:

    为避免类型不匹配,可以使用 Editable 类的 Factory 内部类。 所以你现在可以这样做:

    textview.text = Editable.Factory.getInstance().newEditable("your text")  
    

    【讨论】:

      【解决方案3】:

      或者你可以写一个扩展:

      fun String.toEditable(): Editable =  Editable.Factory.getInstance().newEditable(this)
      

      然后你可以这样使用它:

      mEditText.text = myString.toEditable()
      

      【讨论】:

        【解决方案4】:

        android.text.Editable 来自getText()。在我看来,Kotlin 中的obj.text = value 解析是两步过程。

        1. 编译器尝试查找text 属性或Java 方法getText,从中推断出属性类型
        2. 对于推断的属性类型,编译器会尝试找到相应的属性设置器或 Java 方法setText(PropertyType value)

        由于在 1. 中推断的类型是 EditableeditText.text = "value" 失败并出现 Type mismatch 错误。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-04-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-08-03
          • 1970-01-01
          • 2016-03-22
          • 1970-01-01
          相关资源
          最近更新 更多