I agree with all of this, and I lack strong feelings about whether this should 
be restricted to the same compilation unit or allowed in multiple compilation 
units.

On March 23, 2017 at 1:12:51 PM, Charles Srstka via swift-evolution 
(swift-evolution@swift.org) wrote:

MOTIVATION:

In current Swift, a pattern has emerged among some developers, in order to 
logically group parts of a class or struct’s declaration, particularly around 
protocols:

class Foo {
…
}

extension Foo: SomeProtocol {
...
}

extension Foo: SomeOtherProtocol {
...
}

This has certain appealing characteristics; in addition to the obvious 
organizational property, this pattern also keeps protocol implementations close 
to the declaration of conformance to the protocol. Unfortunately, there are a 
couple of problems:

1. Extensions cannot contain stored properties. This means that if a protocol 
requires a property, and it makes sense for that property to be stored, its 
conformance cannot be completely contained within the extension, but rather 
some of it must be in the main declaration.

2. It’s not uncommon for these protocol conformances to need access to the 
type’s private internal state, but extensions do not have access to private 
members within the state. This necessitates declaring the needed state as 
fileprivate rather than private, a fact has been a primary rallying point in 
the battle that’s currently raging on this mailing list over whether we should 
keep the ‘private’ access modifier, and which I would surmise is probably the 
major remaining use of ‘fileprivate’ in modern Swift code.

3. Since members that are declared ‘fileprivate’ cannot be accessed outside the 
file, these protocol conformance extensions must belong to the same file as the 
original declaration, which can lead to very long file sizes when the code to 
implement a protocol is very long, or when a type supports a large number of 
protocols.

PROPOSED SOLUTION:

Add a keyword to declare only part of a type’s implementation. I am suggesting 
‘partial’ as the keyword, but this can be changed for a better name if needed. 
Partial conformances would be declared like this:

class Foo {
private func somePrivateMethod() { … }
}

partial Foo: SomeProtocol {
var someRequiredProperty: Int = 5

func someRequiredMethod() {
self.somePrivateMethod()
}
}

partial Foo: SomeOtherProtocol {
func someOtherRequiredMethod() {
self.somePrivateMethod()
}
}

When compiling this, the compiler would simply treat all the contents of 
partial declarations as if they were located within the original declaration, 
making the above equivalent to this:

class Foo: SomeProtocol, SomeOtherProtocol {
private func somePrivateMethod() { … }

var someRequiredProperty: Int = 5

func someRequiredMethod() {
self.somePrivateMethod()
}

func someOtherRequiredMethod() {
self.somePrivateMethod()
}
}

Obviously, partial declarations would only be allowed within the same module 
(or submodule, once we get them) as the original declaration.

The advantages to this approach are:

1. Given a pattern that many developers are adopting, this proposal would 
provide a mechanism to follow that pattern properly instead of repurposing a 
mechanism—extensions—which was intended for something else. The Swift manual 
claims that extensions are meant to add things “to a type that is declared 
elsewhere, or even to a type that you imported from a library or a framework,” 
not for separating your own code into parts.

2. Partial implementations can now implement the entirety of a protocol, 
including stored properties if the protocol necessitates them.

3. Since the contents of all partial implementations are considered to be part 
of the same declaration, the contents of partial implementations can access 
private members, which should allow the almost complete elimination of 
‘fileprivate’ from developers’ codebases, simplifying the access control model.

4. Since partial implementations are not dependent on file-based organization, 
they can be stored in separate files, as long as those files are compiled into 
the same module, thus allowing for smaller, leaner, source files that are 
easier to read and understand.

What do you think?

Charles

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to