2017-11-03 20 views
5

W Swift można uniemożliwić zainicjowanie obiektu bezpośrednio, inicjując inicjatora jako prywatny. Możesz to zrobić przy użyciu wzoru Factory.Rozszerzenia Swift na strukturach uniemożliwiają ochronę podczas inicjowania prywatnego.

Ale jeśli utworzysz rozszerzenie, możesz podać inny inicjator i go skompilować. Nie ma znaczenia, czy rozszerzenie znajduje się w tym samym pliku, czy nie. Może to mieć poważne konsekwencje, jeśli na przykład Twoja metoda fabryczna dokonuje weryfikacji danych.

Czy brakuje mi czegoś o prywatnych intencjach? Wydaje się to bardzo złe. Czy mogę temu zapobiec?

struct Foo { 

    let data: Int 

    // factory method 
    static func makeFoo(data: Int) -> Foo { 
     return Foo(data: data) 
    } 

    // private init with data validation 
    private init(data: Int) { 
     guard data < 100 else { 
      fatalError("Foo should only have values under 100") 
     } 
     self.data = data 
    } 
} 

extension Foo { 
    init(someData: Int) { 
     // This bypasses the data validation and puts Foo into an invalid state. 
     self.data = someData 
    } 
} 
+1

Hmm. Powiedziałbym, że to błąd. Wygląda na to, że możesz ominąć to, tworząc 'Foo' jako klasę lub dodając prywatne pole. – Kevin

+0

Tak, działa prywatne pole pomocnicze, ale tylko jeśli znajduje się w innym pliku. Zdecydowanie jest to błąd. – MH175

+2

Połowa twojego problemu to znany błąd odporności. Apple Jordan Rose ma propozycję, aby [wymusić zainicjowanie przez inicjalizatorów struktury międzysystemowej innego inicjalizatora strukturalnego w module] (https://github.com/jrose-apple/swift-evolution/blob/restrict-cross-module-struct- initializers/proposals/nnnn-restrict-cross-module-struct-initializers.md), co oczywiście jest niemożliwe, jeśli inicjatory są prywatne. – zneak

Odpowiedz

0

Zgodnie komentarzach zneak za powyżej, zostanie to zabronione w Swift 5.

Powiązane problemy