Disons que j'ai une variable:
var myObject: MyObject? = null
il devrait être effacé à un endroit:
private fun getMyObject() = myObject ?: MyObject()
et devrait être définitivement non nullable dans un lieu d'utilisation. En Java, je peux faire quelque chose comme ceci:
private MyObject getMyObject(){ if(myObject == null) { myObject = new MyObject() } return myObject }
La question: Comment puis-je y parvenir dans Kotlin?
I a trouvé une suggestion pour utiliser elvis-operator:
myObject?.clear myObject = null
mais cela n'attribue pas de résultat (si une nouvelle instance de MyObject
serait créée) au Variable myObject
.
Veuillez m'aider avec la solution et l'explication. merci d'avance
5 Réponses :
Vous pouvez combiner l'approche de type Java avec l'utilisation de l'opérateur Elvis, en écrivant quelque chose comme ceci:
private fun getMyObject() : MyObject { myObject = myObject ?: MyObject() return myObject as MyObject }
La conversion explicite en MyObject
est nécessaire en raison de Déclaration de myObject
: var myObject MyObject? = nul
. myObject
est un nullable MyObject
mais le type de retour de getObject
est MyObject
.
J'espère que cela pourra vous aider!
Vous pouvez utiliser le champ de sauvegarde de la propriété.
pre> XXX
Pour l'essayer:
class Foo(initBar: String? = null) { private val barDelegate = NullDelegate(initBar) { "Automatically set" } var bar: String by barDelegate // not nullable to outside world fun clearBar() { barDelegate.clear() } } // Reusable. Not thread-safe. class NullDelegate<T>( private var value: T? = null, private val supplier: () -> T ) { operator fun getValue(thisRef: Any?, property: KProperty<*>): T { if (value == null) value = supplier() return value!! } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) { this.value = value } fun clear() { value = null } }
Malheureusement, la propriété doit être nullable pour que cela fonctionne. Vous devrez utiliser !!
ou ?.
partout.
Vous pouvez également utiliser un délégué. Cela prend plus de code pour écrire la propriété mais facilite son utilisation ailleurs.
fun main() { val foo = Foo() foo.bar = "Manually set" println(foo.bar) foo.bar = null println(foo.bar) }
Pour définir bar
sur null code> vous appelleriez
foo.clearBar ()
au lieu de foo.bar = null
.
Excellent moyen d'utiliser les délégués!
Une version plus courte de la version de @ Slaw est la suivante:
var myObject: Any? = null get() = field = field ?: Any() // Does not compile
Cela instanciera un nouveau MyObject
dans le champ de sauvegarde si la propriété est null
sur un accès get
.
Informations supplémentaires: strong>
Vous penseriez probablement à une version plus courte similaire à la suivante
var myObject: MyObject? = null get() { field = field ?: MyObject() return field }
Veuillez garder à l'esprit que cela ne compile pas em> avec le message d'erreur: Les attributions ne sont pas des expressions, et seules les expressions sont autorisées dans ce contexte
.
Le problème est que le getter et le setter d'une propriété ne peuvent pas avoir des types différents. Je suggérerais une propriété privée Nullable distincte et une méthode pour l'effacer:
private var _myObject: MyObject? = null var myObject: MyObject // or val, depending get() { if (_myObject == null) { _myObject = MyObject() } return _myObject!! } set(value: MyObject) { _myObject?.clear() _myObject = value } fun clearMyObject() { _myObject?.clear() _myObject = null }
Si vous avez besoin de ce modèle plus d'une fois, écrivez un délégué .
Vous aviez presque trouvé la bonne réponse avec l'opérateur elvis, la seule partie manquante était de réattribuer l'instance nouvellement créée à la variable myObject
:
private fun getMyObject() = myObject ?: MyObject().also { myObject = it }
Vous pouvez faire la même chose comme en Java:
private fun getMyObject (): MyObject {if (myObject == null) {myObject = MyObject ()} return myObject}
@Sergey - bien sûr, je comprends que je peux utiliser cette approche. la question porte sur la solution la plus élégante