[swift-evolution] An Alternative for Extensibility Modifiers

Károly Lőrentey karoly at lorentey.hu
Tue Jul 12 05:31:56 CDT 2016


On 2016-07-12 09:12:36 +0000, Jonathan Hull via swift-evolution said:

> With all the controversy around proposal 0117, I thought I would take a 
> stab at an alternative approach that attempts to balance the concerns 
> of both sides of the argument.  I don’t know that it would be 
> everyone's first choice, but I think/hope it would be acceptable to the 
> vast majority.
> 
> Take a look here and let me know if you think it is worth flushing out:
> https://gist.github.com/jonhull/a5ac84a16b7a0ffc0c00747998f390d9
> 
> 
> The basic idea (for those who hate clicking links) is to create 3 
> levels of extensibility:
> 	• Open -  The class or method is open to be extended through 
> subclassing/override.
> 	• Sealed - Attempting to subclass/override the class/method will 
> result in a compiler error saying that it is not intended to be 
> extended. Using the ‘unsafe' keyword will allow compilation.
> 	• Final - The class or method can not be subclassed/overridden. 
> Attempting to do so will result in a compiler error.
> 
> These would be orthogonal to access modifiers.  Thus you would write 
> ‘public open’, which is admittedly two words… but together they are 
> actually shorter than the single ‘subclassable’ keyword
> 
> You can also specify different levels of extensibility at different 
> levels of visibility (e.g. ‘public final internal(open)’)
> 
> The default would be ‘sealed internal(open)’ which means it is publicly 
> sealed, but open within the defining module.  This is similar to the 
> default of 0117, except it allows overriding using the ‘unsafe’ keyword 
> (where the user explicitly acknowledges that subclassing/overriding is 
> not supported by the API).

It seems to me adding such an escape hatch makes the entire point of 
the proposal moot.

If I say a class I define is internal or private, you have no business 
poking at it from an external module; if I say my class is sealed or 
final, you have no business subclassing it from an external module. 
Swift provides no escape hatch that exposes internal components of a 
module; I don't see why subclassibility requirements should be treated 
otherwise.

Note that most popular OOP languages provide well-known patterns for 
creating sealed but public classes, where only the author is able to 
create subclasses. These patterns typically involve hiding class 
constructors from external modules. If Swift was changed to support 
sealed classes the same way, would you then propose a language feature 
to defeat access modifiers?

> Thus, we lose some compiler optimizations in the default case (vs 
> 0117), but these can easily be regained by explicitly marking parts of 
> the API as final.  The semantic meaning of the 0117 default is kept, 
> with an escape hatch for problematic API.  Thoughtful framework writers 
> would go through and mark API as either ‘public open’ or ‘public 
> final’.  Less thoughtful framework authors would still get feedback 
> asking them to do so, since nobody likes having the word ‘unsafe’ in 
> their code when they don’t have to.
> 
> This design feels much Swiftier™ to me because it has opt-out safety 
> and opt-in risk.  It protects you from accidentally causing trouble, 
> but gets out of your way when you tell it you know what you are doing.


-- 
Károly
@lorentey




More information about the swift-evolution mailing list