Redeclaration of computed properties in an extension

Viewed 65

Why it is allowed to redeclare computed properties of Swift’s built-in types in an extension, while it is not allowed to redeclare computed properties of my custom types?

struct X {
    var isEmpty: Bool { true }
}

extension X {
    var isEmpty: Bool { true } // error: invalid redeclaration of 'isEmpty'
}

extension String {
    var isEmpty: Bool { true } // allowed
}
1 Answers

This is intentional, but it isn't something you should do generally. The reason it's allowed when importing from another module is to prevent working code from breaking if the module were changed to create a new property. For example, consider the situation where you added your own property:

extension String {
    var isX: Bool { self == "x" }
}

No surprises that this is legal. But what if this is a great idea, so great that they add it to stdlib? Then should your code break? What if they implement it in stdlib as self.lowercased == "x", so it's a little different than yours?

This was a major problem in ObjC. It happened quite a lot, actually, and could lead to bizarre undefined behavior. (I've had to chase down several of these bugs in my time…) The Swift answer is that the extension applies to its context. So in your module, your isEmpty applies. But in stdlib, the stdlib isEmpty applies. You're not overriding it; you're just making your own local extension.

This of course has some downsides, too. It means you might shadow a symbol unintentionally and this could create confusion for later developers. But it's the choice that we currently have. You definitely should not do this on purpose. Whether it should be a warning is another question.

For more history, see Is Redeclaration of Method/Property of Imported Type Allowed via Extension?!? in the Swift forums.

Related