Почему мне нужно объявить необязательное значение как nil явно в Struct - Swift

Вот цитата из документов:

Если у вашего пользовательского типа есть хранимое свойство, которое логически разрешено иметь "нет значения" - возможно, потому что его значение не может быть установлено во время инициализации или потому, что ему разрешено иметь "нет значения" в какой-то более поздней точке - объявить свойство с необязательным типом. Свойства необязательного типа автоматически инициализируются значением nil, что указывает на то, что свойство преднамеренно предназначено для того, чтобы во время инициализации еще не было значения.

Если я делаю это с классом, он отлично работает:

class MyClass {
    var someProperty: String?
}

var myClass = MyClass()
myClass.someProperty // Shows nil

Однако, если я делаю это с помощью типа struct, я получаю сообщение об ошибке при инициализации:

struct MyStruct {
    var someProperty: String?
}

// ERROR
var myStruct = MyStruct()

Ошибка:

Отсутствует аргумент параметра 'someProperty'

Я могу исправить это, объявив его nil явно следующим образом:

struct MyStruct {
    var someProperty: String? = nil
}

// Valid
var myStruct = MyStruct()

Вопрос

Учитывая документацию, я ожидал бы свойств любого типа, которые устанавливаются как необязательные значения по умолчанию равными нулю. Есть ли причина, по которой я должен явно объявить это в структуре?

Почему?

Нет веской причины, как и многие из вас, я просто экспериментирую.

Ответ 1

Оба класса и структуры должны иметь все значения свойств, заданные при их инициализации. Это можно сделать либо с помощью явных значений по умолчанию, либо путем установки значения в назначенном инициализаторе.

Однако, структуры отличаются тем, что они имеют автоматически сгенерированный инициализатор по порядку.

Если вы явно не определяете значение для someProperty, ваша структура имеет только один инициализатор: автоматически сгенерированный по порядку один.

Если вы предоставляете значение по умолчанию, вы получаете два: один, который не принимает аргументов, и тот, который принимает значение для someProperty в качестве аргумента

Из документов:

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

let vga = Resolution(width: 640, height: 480)

В отличие от структур, экземпляры экземпляров не получают по умолчанию по умолчанию инициализатор. Инициализаторы описаны более подробно в Инициализация.

Ответ 2

Я согласен, что это довольно причудливо (если я тоже не пропущу). Для структур с опциями только, возможно, стоит предположить (через Apple bugreport), что в таких случаях по умолчанию добавляется инициализатор по умолчанию без параметров?

Еще одно средство:

var myStruct = MyStruct(someProperty:nil)

Однако, если у вас было много дополнительных членов, это становится неуклюжим.

Ответ 3

Я думаю, что это преднамеренное различие между структурами и классами, что имеет смысл. Например, если у вас есть структура, скажем, трехмерная точка с тремя поплавками для XYZ. Не имеет смысла иметь значение nil для x или y или z. С классом, с другой стороны, это очень важная функция. Если вы думаете о классе загрузчика, например, это идет и загружает текстовый файл и сохраняет его в свойстве. Для этого свойства имеет смысл иметь значение nil, когда класс сначала инициализируется. Поскольку яблоки изменили структуры, которые будут гораздо более тесно связаны с классами, я считаю, что это важное различие. Мое мнение, что установка опционально явно на nil является ошибкой.


Мое рассуждение для этого:

В дополнительная документация все примеры относятся к классам.