Как я могу сделать элементный инициализатор общедоступным, по умолчанию, для структур в Swift?


165

У меня есть быстрый каркас, который определяет структуру:

public struct CollectionTO {
    var index: Order
    var title: String
    var description: String
}

Тем не менее, я не могу использовать неявный член мудрый инициализатор из другого проекта, который импортирует библиотеку. Ошибка «CollectionTO» не может быть инициализирована, поскольку у нее нет доступных инициализаторов. то есть он не дает неявному члену по умолчанию инициализировать ключевое слово public.

var collection1 = CollectionTO(index: 1, title: "New Releases", description: "All the new releases")

Я должен добавить свой собственный метод init следующим образом:

public struct CollectionTO {
    var index: Order
    var title: String
    var description: String

    public init(index: Order, title: String, description: String) {
        self.index = index;
        self.title = title;
        self.description = description;
    }

}

... но я бы предпочел нет, если есть другой способ, кто-нибудь знает?

Ответы:


271

Цитирование руководства:

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

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

Отрывок из «Языка программирования Swift» , раздел «Контроль доступа» .


289
Ну, это раздражает. :(
Дэн Лёвенхерц

7
[ github.com/apple/swift-evolution/blob/master/proposals/… говорит: «Цитирование Криса Латтнера: поведение по умолчанию для элементарного инициализатора Swift имеет, по крайней мере, следующие недостатки (IMO): 2) Контроль доступа + частый инициализация часто требует, чтобы вы реализовали это сами ». Так что, возможно, это просто недостаток, который существует без особой причины. Не удалось найти больше ссылок по этому поводу.
Jano

8
@DanLoewenherz Да, это неудобно. Обоснование таково: «Публичный тип по умолчанию имеет внутренних, а не публичных членов. Если вы хотите, чтобы член типа был общедоступным, вы должны явно пометить его как таковой. Это требование гарантирует, что общедоступный API для типа - это то, что вы выбираете для публикации, и избегает ошибочного представления внутренней работы типа как публичного API ». Выдержка из: Apple Inc. «Язык программирования Swift». интерактивные книги. itun.es/gb/jEUH0.l
bandejapaisa

18
Директива компилятора была бы хороша, чтобы переопределить поведение по умолчанию и сделать его общедоступным.
bandejapaisa

9
Внутренний - ужасный выбор по умолчанию, IMO. Это в основном гарантирует, что вы столкнетесь с неожиданными проблемами при обращении к внешнему модулю в первый раз. Почему бы не использовать все по умолчанию как приватное, чтобы мы могли сразу сказать, когда что-то не имеет правильного уровня доступа, а затем решить, должно ли оно быть публичным или внутренним?
devios1

72

Хотя по умолчанию нет возможности использовать элементный инициализатор по умолчанию, вы можете сделать его быстро, выполнив следующие шаги:

  1. Сделайте объект временно классом вместо структуры
  2. Сохранить
  3. Щелкните правой кнопкой мыши имя класса и выберите refactor -> Generate Memberwise Initializer.
  4. Измените его обратно на структуру

блестящий. не могу отблагодарить вас, чтобы обойти этот быстрый недостаток
Антон Тропашко

1
Работает, а также мотивирует использовать классы вместо структур youtube.com/watch?v=_V2sBURgUBI
Исаак Кэрол Вайсберг,

Это супер совет!
Пейманх

6
Начиная с Xcode 11, вы также можете использовать Generate Memberwise Initializer для структур!
Брок Бэтселл

Фантастика!!! Это не правильный ответ, но очень хороший совет! Мне очень помогли!
GuiOS

3

Пока Apple не изменит это и не сделает его менее раздражающим, вы можете использовать https://github.com/Bouke/SwiftInitializerGenerator (или любой другой) эту вещь для создания публичных инициализаторов. Так будет меньше работы. Попробовал и все работает. Xcode Version 10.0, High Sierra 10.13.6


1

Теперь у нас есть рубиновый гем 💎 для построчного анализа полного файла модели данных swift и добавления модификаторов общедоступного доступа, общедоступных инициализаторов по умолчанию для членов и других вещей в отдельный автоматически генерируемый выходной файл swift.

Этот драгоценный камень называется swift_republic

Пожалуйста, ознакомьтесь со следующей документацией для запуска этого драгоценного камня:

https://github.com/mehul90/swift_republic


1
Отличное решение !! Я уже создал обертку для swift_republicи работает нормально.
Md Shahed Hossain
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.