> On 2016-07-18, at 19:05, John McCall via swift-evolution 
> <swift-evolution@swift.org> wrote:
> The basic effect of Károly's counter-proposal is that every public member of 
> an open class has to be marked either "open" or "final".  That's boilerplate.

My primary point was that there is no need for a middle ground between "final" 
and "open" members.

I want to push my primary point a little more, so let’s forget my secondary 
suggestion to have no default, and let’s set an implicit choice. 

I'd still argue for having no middle ground. “final” seems to be a good 
default; its effect matches the proposal.

> I think you and Károly are evaluating the addition of non-open methods as if 
> they were being added primarily to increase expressive capabilities.  They do 
> marginally increase expressiveness, but I agree that it's not a common 
> situation to explicitly want.  However, neither are non-open classes.  

It's more of an Occam's razor thing. The proposal prevents people from 
unintentionally exposing a wider API area than they intended. I agree with this 
wholeheartedly. I just don't believe that we need to add a brand new access 
level for members to achieve this goal.

Having an implicit "sealed" class level is a much easier sell for me, because 
it is sometimes desirable to expose a sealed class hierarchy, but Swift doesn't 
currently support it well -- AFAICT not as an intentional choice, but rather as 
an unfortunate side-effect of the initializer rules. You could've simply chosen 
to propose making "final" the default for public classes. Kotlin's troubles 
mostly wouldn't apply as long as internal classes would remain open, so I'd 
have supported that too. But rather than this, the proposal is built on top a 
nice solution to the sealed class problem. Solving it is obviously a good idea, 
and it is closely related to the goal of the proposal.

There is no such language problem in Swift 2 with sealed methods: an internal 
open member is sealed by virtue of not being externally visible. It’s 
straightforward to add a public final trampoline in the rare case when a sealed 
member should also be made externally callable. I believe the proposal works 
perfectly well without adding a language feature for this uncommon usecase.

> The goal here is not to create new expressive power, it's to establish a 
> comprehensible intermediate position that's acceptable as a default so that 
> publicizing an API doesn't require so much annotation and bookkeeping.  
> Otherwise, programmers are forced to immediately decide between 
> over-promising (by making the method publicly overridable) or breaking their 
> own code (if they have internal overrides).

But making API public should never be done in a hurry. It includes making the 
API presentable, which involves some amount of refactoring. Granted, if an API 
has internally overridden methods that the author wants to make public but 
sealed, then they'd need to refactor these methods. But given how rare this is, 
and how easy it is to implement the trampoline pattern, is such a trivial 
refactoring step really too much to ask? (There are a number of much more 
complicated refactorings involved in making an API public; e.g., it is often 
the case that a method I want to make public has a parameter or return value 
with a type that I wish to keep internal.)

I believe that apart from this one little wrinkle, the behavior that SE-0117 
proposes can be fully implemented by allowing just "final", "open" and 
"dynamic" members, with "final" being the default for public members of open 
classes, and "open" being the default for all other members (including non-open 
classes).

Is smoothing out that wrinkle worth introducing a whole new default level of 
member overridability? I think this is worth some more discussion.

Note that if we end up with "final” members by default and it turns out to be 
the wrong choice, changing the default to sealed would not be a source-breaking 
change.

> Furthermore, I don't agree that non-open methods add significant new 
> complexity.  For clients of a library, a non-open method is final; there are 
> no semantically-detectable differences (ignoring covariant overrides).  
> Within a library, non-open methods remove the need for some unnecessary 
> bookkeeping.  And just on a conceptual level, the analogy to class behavior 
> is quite simple.

This reminds me: Whether or not we allow the sealed level on methods, I suggest 
we provide a contextual keyword to (optionally) spell it. A "sealed" keyword is 
the obvious choice. This would encourage people to use common terminology, and 
makes it easier to use search engines to find an explanation of the concept. 
Autogenerated API summaries should add the "sealed" keyword.

We never have to spell "internal", but I think it is still very useful that it 
exists.

--
Károly
@lorentey

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

Reply via email to