[swift-evolution] [Proposal] Factory Initializers

Riley Testut rileytestut at gmail.com
Fri Mar 31 18:35:01 CDT 2017


> On Mar 20, 2017, at 8:07 PM, Greg Parker <gparker at apple.com> wrote:
> 
> This needs more explanation. It is allowed for a subclass to implement a convenience initializer that has the same signature as a superclass convenience initializer or a superclass designated initializer. The convenience-over-convenience case is not technically overriding, but it is misleading to say only that a convenience initializer cannot be overridden. Do factory initializers follow exactly the same rules here as convenience initializers?

Yes, that is what I meant. For simplicity, I think the factory initializer inheritance rules should match exactly that of convenience initializers.

> In addition: designated initializers and convenience initializers have rules about which other initializers can be called from an implementation. These rules are intended to guarantee that the chain of designated initializers is called correctly. What are the precise rules for factory initializers calling other initializers? What are the precise rules for non-factory initializers calling factory initializers?

Factory initializers can call any other initializers. Since calling convenience initializers would still call required initializers, the chain would be correct (unless I’m missing something). As for other initializers calling factory initializers, my gut says this should not be allowed. Factory initializers are supposed to initialize and return a value, whereas other initializers implicitly assign to self. Therefore calling a factory initializer from a self-assigning initializer wouldn’t do much, and I don’t see any benefit to allowing this.


> On Mar 21, 2017, at 8:49 AM, David Rönnqvist <david.ronnqvist at gmail.com> wrote:
> 
> Forgive me if that has already been discussed in the email threads prior to the proposal, but what I’m missing from this proposal is a discussion of the problems factory initializers solve (other than the examples at the end) and an explanation of why factory initializers are the right solution to that/those problems in Swift.

I can answer this anecdotally; when learning iOS development and Objective-C, it was (in my opinion) hard to know whether an Objective-C class was meant to be initialized via [[Class alloc] initWithParameters:] or [Class classWithParameters:]. Pre-ARC this did actually have meaning, but post ARC/iOS 5 it just seemed to be whatever the framework developer preferred (not to mention that [Class new] was also another option…).

When Swift combined all these forms into one common Class(parameters:) format, this greatly reduced this cognitive load. However, as outlined in the proposal, this meant that the factory pattern had to be moved out of the initializers and back into class methods. Because of this, now if you want to implement the factory pattern, you’re bringing back this same confusion from Objective-C; the client has to remember whether your class is initialized via standard Class(parameters:) syntax, or by calling a class method Class.classWithParameters(). Ultimately, I don’t believe there should be a difference between the two for the average programmer. You want an instance of the class, so you should retrieve one by calling an initializer. They don’t need to know or care whether the initializer is directly assigning to self or returning a value, as long as they get the value they need.

Beyond this, however, I think the factory initializers on protocols is one of this proposal’s biggest wins. For protocol oriented programming, it’s nice to be apply to supply a default implementation so client’s don’t need to declare their own type. However, if you come across a new codebase/framework, you might not know the difference between the specific type you’re using and the protocol itself (or even which one is which). I’ve personally encountered this many times with Apple’s frameworks, such as UIActivityItemProvider and UIActivityItemSource (which one is the protocol and which one is the type? Hard to know and remember when first using them). With factory initializers on protocol extensions, the initializer can return a private type conforming to the protocol, so again there’s no need to worry about what is the concrete type and what is the protocol.

P.S. Phase 2 End Question

I didn’t realize until today that apparently Swift 4 Phase 2 ends tomorrow. Is this true, and does that mean this is now too late to make it into Swift 4?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170331/79392813/attachment.html>


More information about the swift-evolution mailing list