[swift-evolution] [swift-evolution-announce] [Review #2] SE-0117: Default classes to be non-subclassable publicly
Garth Snyder
garth at garthsnyder.com
Tue Jul 19 03:37:07 CDT 2016
> Taras Zakharko: I did a quick rudimentary regex through AppKit headers looking for stuff like "((n't)|(not)).{1,15}override“ and its true that there seem to be only a few dozens of documented methods where the documentation explicitly warns agains overriding them. I have no idea how reliable the headers are or what the documentation is generated from, but that appears to me to be quite strong evidence in support of Károly’s and others arguments.
That sounds informative and relevant.
Taras didn’t post his results, so I repeated the same basic procedure against the headers included in Xcode 8 beta 3. I’ll describe the procedure I used below, but for the impatient, here’s what I found. Keep in mind that the data quality is pretty low: it derives from comments in header files for libraries written in another language, searched for with one regex. Make of this what you will.
That said, there does not appear to be much obvious support in the existing iOS API for the idea that some kind of method-level indicator of non-overridability would be helpful. Individual methods and properties notated as being non-overridable are exceptionally rare (as are “don’t subclass” classes, for that matter). Among non-overridable methods, virtually all cases would be well handled by the existing “final” specifier, because they are defined in one class and never reimplemented by subclasses.
It’s also interesting, and heartening, to see the general tenor of the header comments that warn developers away from subclassing or overriding things. "Most clients will not need to subclass UITabBarController,” is a typical discouragement. I can’t help wondering how many such demurrals will simply become prohibitions under the new defaults.
Procedure: I ran the regex
((n't)|(not)).{1,15}(override|subclass|specialize|implement)
over everything within
/Applications/Xcode-beta.app/Contents/Developer/Platforms/iPhoneOS.platform
That produced 200 matches spread over 3981 files. I then examined each match in detail. The vast majority of matches were comments of the form “if a subclass does not implement…” or comments about functionality that was in fact not implemented. (That is, noise.)
Six classes were commented as being non-subclassable. Since a decision has already been made to allow Swift to support explicitly non-subclassable classes. I didn’t investigate these in detail. But for reference, they are:
ABNewPersonViewController
ABPeoplePickerNavigationController
AVMetadataObject
NSPointerFunctions
SKView
UITextInputMode
There were 12 methods commented as being non-overridable (the exact terminology varied). They were:
[UIViewController childViewControllerContainingSegueSource:]
[UIStackView +layerClass]
[UIResponder inputAssistantItem] (property)
[NSFileProviderExtension writePlaceholderAtURL:withMetadata:error:]
[NSFileProviderExtension placeholderForURL:]
[NEPacketTunnelProvider setTunnelNetworkSettings:completionHandler:]
[NEAppProxyProvider cancelProxyWithError:]
[NSIncrementalStore newObjectIDForEntity:referenceObject:]
[NSIncrementalStore referenceObjectForObjectID:]
[AUAudioUnit scheduleParameterBlock] (property)
[AUAudioUnit scheduleMIDIEventBlock] (property)
For these, I wanted to answer the question, “Had these classes been written in Swift, would a designation of ‘final’ have sufficed to limit their overridability?” Which is to say, “Are there no subclasses of the classes whose methods or properties bear the ‘don’t override’ notations that also implement these methods?” If there are no subclasses with implementations, then “final” on the original method would be sufficient to keep the method public but forestall unwanted overrides.
To investigate that, I ran nm on the corresponding framework dylib from iPhoneSimulator.platform, then grepped for the first component of the method names. Unfortunately, there’s no code in the AudioUnit.framework directory for either iPhoneSimulator.platform or MacOS.platform, so I couldn’t assess the AUAudioUnit properties. (I’m sure there’s a better way to do this; I just don’t know what it is.)
Of the remaining 10 methods, 9 were never overridden by a subclass within the same framework, meaning that they’d be covered perfectly well by “final”.
The one remaining case is the inputAssistantItem property on UIResponder. That’s implemented both by UIResponder and its indirect descendant UISearchBar. This property is read-only and is used only on iPad; it configures extra controls that appear above the keyboard when a responder interested in keyboard events has the input focus. You configure the assistant items by accessing the inputAssistantItem on an existing view and setting its properties. It’s not obvious to me on initial inspection why exactly inputAssistantItem must never be overridden.
Garth
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160719/ae392807/attachment.html>
More information about the swift-evolution
mailing list