Jak domyślnie ustawić publiczną inicjalizację elementu członkowskiego dla struktur w języku Swift?

164

Mam szybki framework, który definiuje strukturę:

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

Jednak wydaje mi się, że nie mogę użyć niejawnego inicjatora elementu członkowskiego z innego projektu, który importuje bibliotekę. Nie można zainicjować „CollectionTO”, ponieważ nie ma dostępnych inicjatorów. tj. nie przekazuje domyślnemu, niejawnemu inicjatorowi elementu wise, słowa kluczowego public.

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

Muszę dodać własną metodę init w następujący sposób:

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;
    }

}

... ale wolałbym nie, gdyby ktoś wiedział o innym sposobie?

bandejapaisa
źródło

Odpowiedzi:

268

Cytując instrukcję:

„Domyślne inicjatory składowe dla typów struktur Domyślny inicjator składowych dla typu struktury jest uważany za prywatny, jeśli którakolwiek z przechowywanych właściwości struktury jest prywatna. W przeciwnym razie inicjator ma wewnętrzny poziom dostępu.

Podobnie jak w przypadku powyższego domyślnego inicjatora, jeśli chcesz, aby typ struktury publicznej był inicjalizowany za pomocą inicjatora składowego, gdy jest używany w innym module, musisz samodzielnie dostarczyć publiczny inicjator elementu członkowskiego jako część definicji typu. "

Fragment z „Swift Programming Language” , sekcja „Access Control” .

bandejapaisa
źródło
288
Cóż, to denerwujące. :(
Dan Loewenherz
7
[ github.com/apple/swift-evolution/blob/master/propiments/… mówi: „Cytując Chrisa Lattnera: Domyślne zachowanie inicjatora członkostwa w Swift ma co najmniej następujące wady (IMO): 2) Kontrola dostępu + często inicjalizacja członkostwa wymaga samodzielnego wdrożenia ”. Więc może to tylko niedobór, który istnieje bez konkretnego powodu. Nie udało się znaleźć więcej odniesień na ten temat.
Jano
8
@DanLoewenherz Tak, to niewygodne. Uzasadnienie jest następujące: „Typ publiczny domyślnie ma członków wewnętrznych, a nie publicznych. Jeśli chcesz, aby członek typu był publiczny, musisz jawnie oznaczyć go jako taki. To wymaganie gwarantuje, że publicznie dostępny interfejs API dla typu jest czymś, co zdecydujesz się publikować, i pozwala uniknąć omyłkowego prezentowania wewnętrznego działania typu jako publicznego interfejsu API. ” Fragment z: Apple Inc. „Swift Programming Language”. iBooks. itun.es/gb/jEUH0.l
bandejapaisa
18
Dyrektywa kompilatora przydałaby się do przesłonięcia domyślnego zachowania i upublicznienia go.
bandejapaisa
9
Wewnętrzny to okropny wybór dla domyślnego, imo. Zasadniczo gwarantuje, że napotkasz nieoczekiwane problemy podczas pierwszego odwołania do modułu z zewnątrz. Dlaczego nie ustawić domyślnie wszystkiego na prywatne, abyśmy mogli od razu stwierdzić, kiedy coś nie ma odpowiedniego poziomu dostępu, a następnie zdecydować, czy powinno to być publiczne czy wewnętrzne?
devios1
72

Chociaż nie jest możliwe posiadanie domyślnego inicjatora składowego, przynajmniej możesz go szybko utworzyć, wykonując następujące czynności:

  1. Ustaw obiekt tymczasowo jako klasę zamiast struktury
  2. Zapisać
  3. Kliknij prawym przyciskiem myszy nazwę klasy i wybierz Refactor -> Generate Memberwise Initializer
  4. Zmień go z powrotem w strukturę
JP Aquino
źródło
znakomity. nie mogę ci wystarczająco podziękować za obejście tego szybkiego braku
Anton Tropashko
1
Działa i motywuje do faktycznego korzystania z klas zamiast struktur youtube.com/watch?v=_V2sBURgUBI
Isaac Carol Weisberg
To super wskazówka !!
Peymankh
6
Począwszy od Xcode 11, możesz również użyć Generate Memberwise Initializer na strukturach!
Brock Batsell
Fantastyczny!!! To nie jest dobra odpowiedź, ale jest to bardzo dobra wskazówka! Bardzo mi pomogło!
GuiOS
3

Dopóki Apple to nie zmieni i nie sprawi, że będzie mniej irytujące, możesz użyć https://github.com/Bouke/SwiftInitializerGenerator (lub dowolnego innego) do tworzenia publicznych inicjatorów. Będzie więc mniej pracy. Próbowałem i działa. Xcode w wersji 10.0, High Sierra 10.13.6

Zaporozhchenko Oleksandr
źródło
1

Mamy teraz rubinowy klejnot 💎 do analizowania kompletnego pliku szybkiego modelu danych, wiersz po wierszu i dodawania publicznych modyfikatorów dostępu, publicznych domyślnych inicjatorów dla elementów członkowskich i innych rzeczy do oddzielnego automatycznie generowanego pliku wyjściowego szybkiego.

Ten klejnot nazywa się swift_republic

Sprawdź następującą dokumentację dotyczącą uruchomienia tego klejnotu:

https://github.com/mehul90/swift_republic

Mehul Parmar
źródło
1
Niesamowite rozwiązanie !! Stworzyłem już opakowanie swift_republici działa dobrze.
Md Shahed Hossain