Je me demande s’il existe un moyen de vérifier si une variable lateinit
a été initialisée.
import javafx.application.Application
import javafx.event.EventHandler
import javafx.geometry.Insets
import javafx.geometry.Pos
import javafx.scene.Scene
import javafx.scene.control.Button
import javafx.scene.control.ComboBox
import javafx.scene.layout.VBox
import javafx.stage.DirectoryChooser
import javafx.stage.Stage
import Java.io.File
class SeriesManager() {
lateinit var seriesDir: File
val allSeries by lazy {
seriesDir.listFiles().map { it.name }.toTypedArray()
}
}
class SeriesManagerUI : Application() {
override fun start(primaryStage: Stage) {
val sm = SeriesManager()
val setSeriesDirBtn = Button("Change all series location").apply {
onAction = EventHandler {
sm.seriesDir = DirectoryChooser().apply {
title = "Choose all series location"
}.showDialog(primaryStage)
}
}
val allSeriesList = ComboBox<String>().apply {
promptText = "Select a series from here"
isDisable = // I want this to be always true, unless the SeriesManager.seriesDir has been initialized
}
val setCurrentEpisodeBtn = Button("Change the current episode")
val openNextEpisode = Button("Watch the next episode")
val layout = VBox(
setSeriesDirBtn,
allSeriesList,
setCurrentEpisodeBtn,
openNextEpisode
).apply {
padding = Insets(15.0)
spacing = 10.0
alignment = Pos.CENTER
}
primaryStage.apply {
scene = Scene(layout).apply {
minWidth = 300.0
isResizable = false
}
title = "Series Manager"
}.show()
}
}
fun main(args: Array<String>) {
Application.launch(SeriesManagerUI::class.Java, *args)
}
Il y a une amélioration de lateinit
dans Kotlin 1.2 qui permet de vérifier directement l'état d'initialisation de la variable lateinit
:
lateinit var file: File
if (::file.isInitialized) { ... }
Voir l’annonce sur blog JetBrains ou proposition KEEP .
UPDATE: Kotlin 1.2 a été publié. Vous pouvez trouver les améliorations de lateinit
ici:
Essayez de l'utiliser et vous recevrez un UninitializedPropertyAccessException
s'il n'est pas initialisé.
lateinit
est spécifiquement destiné aux cas où les champs sont initialisés après la construction, mais avant leur utilisation réelle (un modèle utilisé par la plupart des infrastructures d'injection). Si ce n'est pas votre cas d'utilisation, lateinit
pourrait ne pas être le bon choix.
EDIT: Basé sur ce que vous voulez faire, quelque chose comme ceci fonctionnerait mieux:
val chosenFile = SimpleObjectProperty<File?>
val button: Button
// Disables the button if chosenFile.get() is null
button.disableProperty.bind(chosenFile.isNull())
En utilisant la propriété .isInitialized
, on peut vérifier l'état d'initialisation d'une variable Lateinit.
if(::file.isInitialized){
//File is initialized
}else{
//File is not initialized
}
Pour vérifier si un lateinit var
a été initialisé ou non, utilisez un .isInitialized
sur la référence à cette propriété:
if (foo::bar.isInitialized) {
println(foo.bar)
}
Cette vérification n’est disponible que pour les propriétés accessibles lexicalement, c’est-à-dire déclarées dans le même type ou dans l’un des types externes, ou au plus haut niveau dans le même fichier.
kotlin.UninitializedPropertyAccessException: lateinit property clientKeypair has not been initialized
Bytecode dit ... bla bla ..
public final static synthetic access$getClientKeypair$p(Lcom/takharsh/ecdh/MainActivity;)Ljava/security/KeyPair;
`L0
LINENUMBER 11 L0
ALOAD 0
GETFIELD com/takharsh/ecdh/MainActivity.clientKeypair : Ljava/security/KeyPair;
DUP
IFNONNULL L1
LDC "clientKeypair"
INVOKESTATIC kotlin/jvm/internal/Intrinsics.throwUninitializedPropertyAccessException (Ljava/lang/String;)V
L1
ARETURN
L2 LOCALVARIABLE $ this Lcom/takharsh/ecdh/MainActivity; L0 L2 0 MAXSTACK = 2 MAXLOCALS = 1
Kotlin crée une variable locale supplémentaire de la même instance et vérifie si elle est nulle ou non. Si cette valeur est null, elle renvoie alors 'throwUninitializedPropertyAccessException', sinon elle renvoie l'objet local. Au-dessus du bytecode expliqué ici Solution Depuis kotlin 1.2, il permet de vérifier si la météo a été initialisée ou si la var a été initialisée ou non avec .isInitialized
Réponse acceptée me donne une erreur de compilation dans Kotlin 1.3+
, je devais mentionner explicitement le mot clé this
avant ::
. Ci-dessous le code de travail.
lateinit var file: File
if (this::file.isInitialized) {
// file is not null
}