"self" используется до того, как все сохраненные свойства будут инициализированы

Я работаю над обучаемой быстрой площадкой и обновляя ее до Swift 2.0, когда изучаю язык. Следующий код (который, вероятно, работал с предыдущими версиями Swift) теперь генерирует две ошибки: "self" используется до того, как все сохраненные свойства инициализируются "и" Constant "self.capitalCity, используемый до инициализации"

class Country
{
    let name: String
    let capitalCity: City!

    init(name: String, capitalName: String)
    {
        self.name = name
        self.capitalCity = City(name: capitalName, country: self)
    }
}

class City
{
    let name: String
    unowned let country: Country

    init(name: String, country: Country)
    {
        self.name = name
        self.country = country
    }
}

чтение ответа на аналогичный вопрос Я вижу, что я могу изменить let capitalCity: City! на var capitalCity: City!, и синтаксическая ошибка будет решена.

Я понимаю, что в этом надуманном примере страна-столица может измениться, так что это будет хорошо, но что, если бы был случай, когда значение действительно было постоянным...

Есть ли способ разрешить синтаксическую ошибку, сохраняя константу capitalCity?

Ответ 1

В этом случае я предлагаю вам сделать свойство переменной, но скрывать его (сделать его похожим на константу) через вычисленное свойство:

class Country {
    let name: String

    private var _capitalCity: City!
    var capitalCity: City {
        return _capitalCity
    }

    init(name: String, capitalName: String) {
        self.name = name
        self._capitalCity = City(name: capitalName, country: self)
    }
}

Ответ 2

Есть ли способ разрешить синтаксическую ошибку, сохраняя capitalCity константу?

Не так, как у вас есть вещи. Источником проблемы является то, что для установки capitalCity вам нужно создать Город, country которого self. Это использование self, против которого компилятор возражает:

self.capitalCity = City(name: capitalName, country: self)
                                                    ^^^^

Поскольку вы настроили City country как константу, вы должны указать это значение при инициализации своего города. Таким образом, у вас нет выхода; вы должны сделать capitalCity необязательным var, чтобы иметь другое начальное значение, которое является законным, а именно nil. Ваше предлагаемое решение действительно работает следующим образом:

class Country
{
    let name: String
    var capitalCity: City! = nil // implicit or explicit

    init(name: String, capitalName: String)
    {
        self.name = name
        // end of initialization!
        // name is set (to name), and capitalCity is set (to nil)...
        // ... and so the compiler is satisfied;
        // now, we _change_ capitalCity from nil to an actual City,
        // and in doing that, we _are_ allowed to mention `self`
        self.capitalCity = City(name: capitalName, country: self)
    }
}