mardi 27 février 2018

Why Swift ternary operator works so strange

Suppose that we have a class:

class Test: ExpressibleByNilLiteral {
    required init(nilLiteral: ()) {
    }

    init(_ text:String) {

    }
}

and we want to create instance only if some condition is false:

let condition = false

and use this code (1):

var test: Test? = condition ? Test("Z") : nil

as my understanding, in other languages and by this reference, code above is equal to:

var test: Test?
if condition {
    test = Test("Z")
}
else {
    test = nil
}

but in fact in the first case we get not nil, but an non-optional instance of the class Test. In other words, code (1) actually works like this:

let test: Test? = condition ? Test("Z") : Test(nilLiteral: ())

moreover, expression (condition ? Test("Z") : nil) returns regular, non-optional value, so we can write something like:

let test: Test = condition ? Test("Z") : nil

without compilation errors.

If we try class without ExpressibleByNilLiteral, we get nil or compilation error, depending on variable type, as expected:

class Test2 {
    init(_ text:String) {

    }
}

let test2: Test2? = condition ? Test2("Z") : nil // test2 == nil
let test2: Test2 = condition ? Test2("Z") : nil // compilation error

More interesting things:

let test: Test = nil // non-optional instance initialized with nil
let test: Test? = nil // optional, nil

So, the question is: why we get this?

let test: Test? = nil // optional, nil
let test: Test? = false ? Test("Z") : nil // non-optional instance

Aucun commentaire:

Enregistrer un commentaire