Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin initialization: how to fail

I need to parse Firebase DataSnapshot (a JSON object) into a data class, whose properties include enum and list. So I prefer parsing it manually by passing the DataSnapshot into a secondary constructor. However, I want the construction to fail if some fields are missing in the DataSnapshot. In Swift, it has failable initializer that returns null so I know it has failed. How to do that in Kotlin?

The following is my attempt, but I assume you can't just return from a constructor, right?

data class Unit(val name: String, val type: UnitType, val components: List<Component>) {
    constructor(snapshot: DataSnapshot) {
        name = snapshot.child("name").value as? String ?: return
        val typeString = snapshot.child("type").value as? String ?: return
        type = UnitType.values().firstOrNull { it.abbrv == typeString } ?: return
        ...
    }

}
like image 318
Jack Guo Avatar asked Jul 12 '18 14:07

Jack Guo


People also ask

Why does kotlin init block?

Kotlin initThe code inside the init block is the first to be executed when the class is instantiated. The init block is run every time the class is instantiated, with any kind of constructor as we shall see next. Multiple initializer blocks can be written in a class.

How do I initialize a class in Kotlin?

Constructors The primary constructor is a part of the class header, and it goes after the class name and optional type parameters. The primary constructor cannot contain any code. Initialization code can be placed in initializer blocks prefixed with the init keyword.

What does :: mean in Kotlin?

?: takes the right-hand value if the left-hand value is null (the elvis operator). :: creates a member reference or a class reference.


2 Answers

There is the require function which was designed for this purpose:

// ...
init {
    require(foo == "bar") {
        "$foo should be equal to 'bar'"
    }
}

There is also requireNotNull, check, error and some others. These are called Preconditions in Kotlin. There is no magic here, they are just some helper functions. You can check the actual source here, it is very useful. There is a related blog post about the topic here.

like image 179
Adam Arold Avatar answered Nov 15 '22 10:11

Adam Arold


No, you can't just return from a constructor - it doesn't make much sense conceptually - but since I'm fairly naive on Kotlin syntax, I'll answer to a more broad paradigm here.

Your data class is not responsible for error checking or error handling. It is only responsible for storing data. Therefore, you should rely on a factory pattern to parse the result of a DataSnapshot and conditionally instantiate a new instance of Unit if and only if no fields are missing.

like image 25
Makoto Avatar answered Nov 15 '22 10:11

Makoto