[swift-evolution] [Review #3] SE-0117: Allow distinguishing between public access and public overridability
garth at garthsnyder.com
Thu Jul 21 17:29:04 CDT 2016
[ Long, sorry… ]
This version is a big step forward! Thanks for the continued work and comments...
I want to propose a small reframing that I think would help to clarify some of the remaining issues. It’s not really a “counterproposal” because I don’t think it actually changes all that much about the proposal. It’s more a question of how one conceptualizes the changes and fits them into the existing framework.
The gist is: let’s let the second shoe drop and admit that in the current proposal, “open” is now an access level modifier, pure and simple.
In the original proposal (and the ensuing discussion), there was tacit agreement that subclassability/overridability and access levels should be orthogonal. However, given the direction that the design has taken since then, I think we should revisit that decision.
open IS in fact an access level. I can’t say it any better than the proposal itself: “Since the first release of Swift, marking a class public has provided two capabilities: it allows other modules to instantiate and use the class, and it also allows other modules to define subclasses of it. Similarly, marking a class member (a method, property, or subscript) public has provided two capabilities: it allows other modules to use the member, and it also allows those modules to override it…This proposal suggests distinguishing these concepts. A public member will only be usable by other modules, but not overridable. An open member will be both usable and overridable. Similarly, a public class will only be usable by other modules, but not subclassable. An open class will be both usable and subclassable.”
In other words, subclassability/overridability always was an access level issue. All we are doing now is subdividing public into two separate sublevels, public and open. Just as public subsumes all the privileges of internal, open subsumes public.
First, the vast majority of resistance to this proposal (including my own, originally) has centered on the sense that coding options are being removed for potentially or partially ideological reasons (see SoftwareDevelopmentAttitude <http://martinfowler.com/bliki/SoftwareDevelopmentAttitude.html>), without clear value being offered in return. Reframing open as an access level completely nullifies this objection. “internal” is already the default access level, and the community seems very comfortable with this. For public APIs, developers are now simply required to make a neutral choice between public and open. There’s no strong-arming and no surprising imposition of new restrictions. Developers just have to make exactly the same, explicit access level decisions they did before. (For public API, the default is already so restrictive as to be moot. No accusations of “you picked the wrong default”!)
Second, framing open as an access level automatically resolves the ambiguity between proposal options #1 and #2, in favor of #1 (classes can be marked open). The reason there’s ambiguity about this choice is that there’s ambiguity about what open "really is.” Pin down exactly how open fits into the larger language, and the resolution is obvious. We already know what it means for a class and its members to have different access levels: the members are clamped to the access level of the container. All of the arguments that led to this convention — chiefly, that one may want to keep eventual publication in mind while developing and then be able to “flip the switch” in one place — apply equally to the additional privileges of open.
Third, developers already understand access levels and how they interact. If open is just an access level, all of this proposal’s changes can be fully and naturally described in one line: “public no longer includes the right to subclass or override. To get the behavior formerly known as public, use open instead.” Clear, concise, and not very controversial.
Fourth, bending over backwards to insist that open is not an access level leads to a variety of weird effects and special cases. For example, the fact that open implies public unless otherwise stated, which is mighty strange for modifiers that are supposedly orthogonal. Not to mention all the potential headbutts mentioned earlier by Xiaodi Wu; I agree that open in combination with internal seems oxymoronic. All of these nits would just go away if open were an access level. Again, all of this is the case because open really does quack like an access level and walk like an access level.
Q: “But what about access-leveled entities for which ‘open’ doesn’t make sense? What does ‘open struct’ mean?”
A: It doesn’t mean anything and should be an error. Simple. It’s not as if there weren’t all kinds of above-grammar-level restrictions in the current design…
Q: “What about conflicts with other modifiers, e.g. ‘open is not permitted on declarations that are explicitly final or dynamic’? Isn’t it weird that a simple access level could cause this kind of conflict?”
A: Au contraire, it’s final and dynamic that impose special requirements. You can just as easily flip this around: “final may not be applied to objects at the open access level”. Doesn’t that make more sense anyway?
Q: “You yourself (Garth) have argued that there’s no value to being able to forbid subclassing at the class level, and others have taken this position as well. So why are you now so eager to add ‘open’ to class definitions?”
A: Because it leads to a simple, consistent, and uncontroversial design. I do think there is value in being able to “flip the switch” at the class level as well. From the technical/compiler perspective, it seems like most benefits derive from method-level restrictions (as the current proposal seems to suggest). However, from the perspective of API clients, the top-level question is always going to be “should I be subclassing this or not?” I wouldn’t argue in favor of a class-level keyword just for the purpose of documenting intention, but since we get it for free with these other benefits, I’m all for it.
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the swift-evolution