[swift-evolution] Why you can't make someone else's class Decodable: a long-winded explanation of 'required' initializers

Itai Ferber iferber at apple.com
Fri Aug 4 11:23:52 CDT 2017


To clarify a bit here — this isn’t a "privilege" so much so as a 
property of the design of these classes.
`NSData`, `NSString`, `NSArray`, and some others, are all known as 
_class clusters_; the classes you know and use are essentially abstract 
base classes whose implementation is given in private concrete 
subclasses that specialize based on usage. These classes are essentially 
an abstract interface for subclasses to follow. You can take a look at 
the [subclassing notes for 
`NSArray`](https://developer.apple.com/documentation/foundation/nsarray#1651549), 
for instance, to see the guidelines offered for subclassing such a base 
class.

The reason you can relatively safely offer `static` extensions on these 
types is that it’s reasonably rare to need to subclass them, and at 
that, even rarer to offer any interface _besides_ what’s given by the 
base class. You can rely on the, say, `NSString` interface to access all 
functionality needed to represent a string. If I were to subclass 
`NSString` with totally different properties, though, your `static` 
extension might not take that into account.

Not all types you list here are class clusters, BTW, but they largely 
fall into the same category of "never really subclassed". There’s no 
real need for anyone to subclass `NSDate` or `NSDecimalNumber` (since 
they’re pretty low-level structural types), so this should apply to 
those as well.

In general, this property applies to all types like this which are 
rarely subclassed. In Swift, types like this might fall under a `final 
class` designation, though in Objective-C it’s more by convention/lack 
of need than by strict enforcement. There’s a reason we offer some of 
these as `struct`s in Swift (e.g. `Date`, `Decimal`, `Data`, etc.).

On 3 Aug 2017, at 21:03, Gwendal Roué wrote:

>> Le 3 août 2017 à 19:10, Itai Ferber <iferber at apple.com> a écrit :
>>
>> I just mentioned this in my other email, but to point out here: the 
>> reason this works in your case is because you adopt these methods as 
>> static funcs and can reasonably rely on subclasses of NSData, 
>> NSNumber, NSString, etc. to do the right thing because of work done 
>> behind the scenes in the ObjC implementations of these classes (and 
>> because we’ve got established subclassing requirements on these 
>> methods — all subclasses of these classes are going to look 
>> approximately the same without doing anything crazy).
>>
>> This would not work for Codable in the general case, however, where 
>> subclasses likely need to add additional storage, properties, encoded 
>> representations, etc., without equivalent requirements, either via 
>> additional protocols or conventions.
>
> Thaks for your explanation why a static method in a protocol is able 
> to instantiate non final classes like NSData, NSDate, NSNumber, 
> NSDecimalNumber, NSString, etc.
>
> Is this "privilege" stable? Can I rely on it to be maintained over 
> time? Or would it be a better idea to drop support for those low-level 
> Foundation classes, because they'll eventually become regular classes 
> without any specific support? This would not harm that much: Data, 
> Date, String are there for a reason. NSDecimalNumber is the only one 
> of its kind, though.
>
> Gwendal
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170804/12583989/attachment.html>


More information about the swift-evolution mailing list