How to initialize bidirectional graph in Swift?

隐身守侯 提交于 2021-02-11 07:26:50

问题


I have some classes that create a graph with "back pointers". I tried to make the back pointers unowned (they'd create cycles otherwise) and initialize them in my init(), but that creates problems with self references. How am I supposed to get around this?

class Parent {
    var child1:Child
    var child2:Child
    unowned var myOwner:Thing

    init(myOwner:Thing) {
        child1 = Child(parent: self) // Compiler errors here
        child2 = Child(parent: self) // and here
        self.myOwner = myOwner
    }
}

class Child {
    unowned var parent:Parent

    init(parent:Parent) {
        self.parent = parent
    }
}

The error I get is

'self' used before all all stored properties are initialized

回答1:


You have that error because Swift enforces that all variables must have a value before you can use self to avoid your instance not being fully initialised. In your case you have two options:

1. Mark child1 and child2 as implicitly unwrapped optionals:

 class Parent {
    var child1: Child!
    var child2: Child!
    unowned var myOwner:Thing

    init(myOwner:Thing) {
        // Note - myOwner is being set before the children.
        self.myOwner = myOwner

        child1 = Child(parent: self) 
        child2 = Child(parent: self) 
    }
}

This results in no errors because both child1 and child2 have a default value of nil, which you are then changing in init.

2. Use lazy instantiation:

class Parent {
    lazy var child1: Child = Child(parent: self)
    lazy var child2: Child = Child(parent: self)
    unowned var myOwner:Thing

    init(myOwner:Thing) {
        self.myOwner = myOwner
    }
}

This results in no errors because a lazy property's value is only calculated when it is first used, therefore self is guaranteed to have been fully initialised.

Hope that helps.



来源:https://stackoverflow.com/questions/29932151/how-to-initialize-bidirectional-graph-in-swift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!