As a developer with 7+ years writing Swift professionally, I still find this area of Swift confusing and unintuitive. Here are a few weird scenarios to show what I mean:
Nesting
public extension Foo {
struct Bar {
enum Baz {}
}
}
Quiz: which of these is public
?
- A)
Bar
- B)
Bar
andBaz
If you guessed A), you're right! However, if you had to read it again to be able to answer, imagine doing this hundreds of times during a regular working day.
In my experience, this causes developer reading fatigue to build up, especially considering more tricky scenarios like:
public extension Foo {
struct Bar {
public enum Baz {}
var foobar: String
}
}
public extension Foo.Bar {
var foobaz: Int
}
At a glance, you'd guess both foobar
and foobaz
are internal properties, but in fact only foobaz
is! Notice also the incosistency between not needing public
for Bar
but requiring it for Baz
even if indented within it. When iterating on this code, one must always check whether the surrounding context of their declaration is a scoped extension, and adjust their declaration accordingly trying to remember the correct behavior every time. Not great DX.
Protocol conformance
public extension Foo: BarProtocol { // error: 'public' modifier cannot be used with extensions that declare protocol conformances
func baz() {}
}
So this directly contradicts the behavior exposed above, and is yet another thing to keep in mind when writing extensions. Again, not great DX.
Private extensions
public struct Foo {}
extension Foo {
private func bar() {}
}
private extension Foo {
func baz() {}
}
func main() {
Foo().bar() // error: 'bar' is inaccessible due to 'private' protection level
Foo().baz() // ✅ — what?!
}
I'm sure there are some other confusing scenarios that come to mind, but here are some that just came to me in a span of a few seconds, which IMO is troublesome and should at least be discussed.
I'd like to know the community's thoughts. Have you ever struggled with this? Does it grant removing scoped extensions in a future major language release?