J'essaie de passer mon projet Android à Kotlin. J'ai une EditText
(une sous-classe de TextView
) pour laquelle je veux définir un conseil et un texte par programme. L'indice fonctionne comme prévu. Pour le texte, cependant, je reçois une exception d'incompatibilité de type si j'essaie de le faire à l'aide de la syntaxe Kotlin:
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
Si nous regardons la déclaration, nous trouverons des signatures identiques héritées de TextView
:
public final void setHint(CharSequence hint)
public final void setText(CharSequence text)
J'avais l'impression que x.y = z
était un raccourci pour x.setY(z)
mais apparemment, cette impression était fausse. setText()
est traité comme une méthode normale plutôt que comme un configurateur, mais quelle est la différence entre ces deux méthodes qui rend le compilateur se comporter différemment? La seule chose à laquelle je puisse penser est que TextView
a une propriété mHint
mais je ne pense pas que ce soit le cas.
Une autre chose que je ne comprends pas très bien, c’est d’où vient Android.text.Editable
? Il n'y a pas de méthode setText(Editable)
correspondante ni de champ public de ce type.
Merci.
Lors de la génération d'une propriété synthétique pour une paire d'accesseurs/fixateurs Java, Kotlin recherche d'abord un agent d'accesseur. Le getter est suffisant pour créer une propriété synthétique avec un type du getter. D'autre part, la propriété ne sera pas créée si seul un poseur est présent.
Quand un setter entre en jeu, la création de propriété devient plus difficile. La raison en est que le getter et le setter peuvent avoir un type différent. De plus, le getter et/ou le setter peuvent être remplacés dans une sous-classe.
Dans votre cas, la classe TextView
contient une getter CharSequence getText()
et une setter void setText(CharSequence)
. Si vous aviez une variable de type TextView
, votre code fonctionnerait correctement. Mais vous avez une variable de type EditText
. Et la classe EditText
contient une fonction getter Editable getText()
surchargée, ce qui signifie que vous pouvez obtenir une Editable
pour une EditText
et définir une Editable
sur une EditText
. Par conséquent, Kotlin crée raisonnablement une propriété synthétique text
de type Editable
. La classe String
n'est pas Editable
, c'est pourquoi vous ne pouvez pas affecter une instance String
à la propriété text
de la classe EditText
.
Pour éviter les incompatibilités de types, vous pouvez utiliser la classe interne Factory de la classe Editable. Vous pouvez donc maintenant faire quelque chose comme:
textview.text = Editable.Factory.getInstance().newEditable("your text")
Le Android.text.Editable
provient de la getText()
. Il me semble que la résolution obj.text = value
dans Kotlin est un processus en 2 étapes.
text
ou une méthode Java getText
à partir de laquelle il déduit le type de propriétésetText(PropertyType value)
Puisque dans le 1. le type inféré est Editable
, le editText.text = "value"
échoue avec l'erreur Type mismatch
.
Sinon, vous pouvez écrire une extension:
fun String.toEditable(): Editable = Editable.Factory.getInstance().newEditable(this)
Vous pouvez ensuite l'utiliser comme tel:
mEditText.text = myString.toEditable()