Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
359 views
in Technique[技术] by (71.8m points)

closures - Swift- variable not initialized before use (but it's not used)

Currently I've got some swift code like this:

class C {
   let type: Type;
   var num = 0;
   init() {
       self.type = Type({ (num: Int) -> Void in
           self.num = num;
       });
   }
}

The Swift compiler refuses to permit it, saying that I've referenced self.type before it's initialized, even though that's clearly completely untrue. Furthermore, I can't employ the workaround found in other questions/answers, because the type is not optional, and it's immutable, so it can't be initialized with nil pointlessly first.

How can I make the Swift compiler accept this perfectly valid code?

This has nothing to do with returning from the initializer early. The callback is executed asynchronously- it is stored and then used later.

I also have a few further lets that are initialized after this one. I would have to turn them all into mutable optionals, even though they're not optional and can't be mutated.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This works:

class C {
    var type: Type?;
    var num = 0;
    init() {
        self.type = Type({ (num: Int) -> Void in
            self.num = num;
        });
    }
}

I assume you knew that. But you want to know why your version isn't working.

Now for the tricky part: for the line

self.num = num;

to work, the compiler has to pass self to inside the closure. The closure could be and probably is executed inside of the constructor of Type.

This is as if you had written

self.type = Type({ (self: C, num: Int) -> Void in
    self.num = num    
});

which is syntactically wrong but explains what the compiler has to do to compile your code.

To pass this necessary instance of self to the constructor of Type, self has to be initialized. But self isn't initialized, because you are still in the constructor.

The compiler tells you which part of self is not initialized, when you try to pass self to the constructor of Type.

P.S.

obviously Type knows num in your code. If you want to use let in C instead of var you could do...

class Type {
    let num: Int
    init () {
        num = 3
    }
}
class C {
    let type: Type;
    var num = 0;
    init() {
        self.type = Type();
        num = type.num
    }
}

or even

class C {
    let type: Type;
    var num: Int {
        return type.num
    }
    init() {
        self.type = Type();
    }
}

depending on whether you want num to change or not. Both examples compile without error.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...