OK, here’s an idea I’m setting up as a target to be shot down:
-
Let’s ignore (for now) protocols that have an associated type.
-
Let’s avoid fixating on whether changes are source-breaking, but circle back around to that issue later if necessary.
-
Let’s stipulate that we eliminate the distinction between a protocol declaration and a protocol extension: a protocol is an amalgamation of itself and all its extensions. (I’m not sure of all of the implications of this.)
-
A member declaration ("requirement") in a protocol is by default both a behavior (visible to clients using conforming types) and a customization point (implementable by a conforming type). Such a declaration may or may not have a default implementation in the protocol itself. (If it doesn’t, all conformers must implement it, as now).
-
A member declaration may be marked
final
, meaning that it is a protocol behavior (visible to clients) but not a customization point (not implementable by conformers). It must have a default implementation in the protocol.
Edit: This doesn't imply that the member is statically dispatched. It just means that the default implementation can be supplanted. (Think "overridden", but let's not actually use that word except with classes.)
-
A member declaration may be marked
private
, meaning that it is not visible to clients, but may be implemented or used by conformers. (This is slightly abusing the meaning ofprivate
but not by much, I think.) -
A member declaration may be marked both
final
andprivate
, meaning that is it a "utility" property or method usable by conformers, but not implementable by them. -
Conformers providing an implementation for a customization point must name their declaration
P.m
orP.m(
…)
, whereP
is the name of the protocol with property or methodm
as a customization point. To ease the transition, the compiler should accept justm
in the conformer declaration, with a warning that theP.
should be specified, provided there’s no ambiguity between conformances to two different protocols. (If there’s ambiguity, the warning should be an error instead.)
Edit: It's not clear to me whether there's a use case for a single declaration that satisfies two unrelated protocols P
and Q
simultaneously. If so, then there's a potential syntax in (P&Q).m
which is horrible but at least viable.
The point of #8 is to avoid adding a keyword to indicate that the member is intended to be a conformance. Any benefit in disambiguating multiple protocol conformances is just a side-effect.
- At use sites, protocol members may be referred to as
someVariable.P.m
orsomeVariable.P.m(
…)
, but if there is no ambiguity with other protocols, the more usual syntaxsomeVariable.m
orsomeVariable.m(
…)
may be used.
Edit: I hate this someVariable.P.m
syntax. Something like it is only needed if the variable's type has separate conformances to unrelated protocols, as in #8.
-
Conformers are not allowed to declare a member with the same declaration name as a name in a protocol to which it conforms, but not have that method be a conformance.
-
[Some rule that resolves the problem where subclass override methods are ambiguous in regards to protocol methods to which a superclass provides an implementation that overrides a default implementation (if this isn’t somehow covered by the other rules).]