Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift extensions on structs make private initialization protection impossible

Tags:

swift

In Swift you can prevent an object from being initialized directly by making the initializer private. You might want to do this with a Factory pattern.

But if you create an extension, you can provide a different initializer and it compiles. It doesn't matter if the extension is in the same file or not. This could have serious consequences if your factory method does some data validation, for example.

Am I missing something about private inits? This seems very bad. Can I prevent this?

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
    }
}
like image 318
MH175 Avatar asked Nov 03 '17 00:11

MH175


1 Answers

As per zneak's comments above, this will be disallowed in Swift 5.

like image 187
MH175 Avatar answered Nov 20 '22 03:11

MH175