2017-11-03 8 views
5

Swiftでは、イニシャライザをプライベートにすることで、オブジェクトが直接初期化されるのを防ぐことができます。これをFactoryパターンで行うことができます。構造体上の拡張機能により、プライベート初期化の保護が不可能になる

ただし、拡張子を作成すると、別の初期化子を提供してコンパイルできます。拡張子が同じファイル内にあるかどうかは関係ありません。たとえば、ファクトリメソッドがいくつかのデータ検証を行う場合、これは重大な結果を招く可能性があります。

プライベートinitsについて何か不明ですか?これは非常に悪いようです。これを防ぐことはできますか?上記あたりzneakのコメントとして

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

うーんで禁止されます。私はこれがバグだと言いたい。 'Foo'をクラスにするか、プライベートフィールドを追加するかのいずれかで回避することができます。 – Kevin

+0

はいプライベートバッキングフィールドは動作しますが、それが異なるファイルにある場合のみです。間違いなくそこにバグ。 – MH175

+2

問題の半分は既知の回復力のバグです。 AppleのJordan Roseは、[モジュール間の構造体初期化子が別のモジュール内構造体初期化子を呼び出すように強制する]提案をしています(https://github.com/jrose-apple/swift-evolution/blob/restrict-cross-module-struct- initializers/proposals/nnnn-restrict-cross-module-struct-initializers.md)。もちろん初期化子がプライベートであれば不可能です。 – zneak

答えて

0

、これはスウィフト5.

関連する問題