The reason for the additional “factory” keyword would be to differentiate it 
from other initializers because it actually “returned" a value. For the record, 
I am entirely in support of modifying convenience initializers to return 
instances directly; I assumed (incorrectly it seems!) that the ability to 
return directly from an initializer was intentionally left out, for whatever 
reason. I agree using the convenience initializer syntax with an explicit 
return type would be a better approach, and would be more in-line with what you 
can do with initializers in Objective-C :-)

If this is already implemented in the compiler, I would love to certainly push 
this idea forward! I genuinely believe this could add great value to the 
language, without changing the fundamentals too much.

> On Dec 17, 2015, at 6:25 PM, Chris Lattner <[email protected]> wrote:
> 
>> 
>> On Dec 17, 2015, at 1:41 PM, Riley Testut via swift-evolution 
>> <[email protected]> wrote:
>> 
>> Recently, I proposed the idea of adding the ability to implement the "class 
>> cluster" pattern from Cocoa (Touch) in Swift. However, as we discussed it 
>> and came up with different approaches, it evolved into a functionality that 
>> I believe is far more beneficial to Swift, and subsequently should be the 
>> focus of its own proposal. So here is the improved (pre-)proposal:
>> 
>> # Factory Initializers
>> 
>> The "factory" pattern is common in many languages, including Objective-C. 
>> Essentially, instead of initializing a type directly, a method is called 
>> that returns an instance of the appropriate type determined by the input 
>> parameters. Functionally this works well, but ultimately it forces the 
>> client of the API to remember to call the factory method instead, rather 
>> than the type's initializer. This might seem like a minor gripe, but given 
>> that we want Swift to be as approachable as possible to new developers, I 
>> think we can do better in this regard.
>> 
>> Rather than have a separate factory method, I propose we build the factory 
>> pattern right into Swift, by way of specialized “factory initializers”. The 
>> exact syntax was proposed by Philippe Hausler from the previous thread, and 
>> I think it is an excellent solution:
>> 
>> class AbstractBase {
>>   public factory init(type: InformationToSwitchOn) {
>>       return ConcreteImplementation(type)
>>   }
>> }
>> 
>> class ConcreteImplementation : AbstractBase {
>> 
>> }
> 
> I’m confused, isn’t this already handled by “convenience” initializers?  
> 
> What we lack now is the ability to use the AbstractBase(42) syntax the 
> produce something with a static type of ConcreteImplementation.  This is 
> something expressible in Objective-C, and something that Swift can currently 
> import into Objective-C, but that you can’t write directly in Swift code 
> right now.
> 
> The approach that I would suggest is a simple extension of the grammar, to 
> allow "-> T” on a convenience initializer.  In this case, you could write:
> 
> 
> class AbstractBase {
>   convenience init(type: InformationToSwitchOn) -> ConcreteImplementation {
>       return ConcreteImplementation(type)
>   }
> 
> and then "AbstractBase(stuff)” would produce a value with the static type of 
> ConcreteImplementation.  This syntax is already produced by the AST printer 
> for imported ObjC stuff, so we have much of the mechanics for this already in 
> the compiler.  It would be great to see someone push this forward!
> 
> -Chris
> 
> 
> 
> 
>> 
>> Why exactly would this be useful in practice? In my own development, I’ve 
>> come across a few places where this would especially be relevant:
>> 
>> ## Class Cluster/Abstract Classes
>> This was the reasoning behind the original proposal, and I still think it 
>> would be a very valid use case. The public superclass would declare all the 
>> public methods, and could delegate off the specific implementations to the 
>> private subclasses. Alternatively, this method could be used as an easy way 
>> to handle backwards-compatibility: rather than litter the code with branches 
>> depending on the OS version, simply return the OS-appropriate subclass from 
>> the factory initializer. Very useful.
>> 
>> ## Protocol Initializers
>> Proposed by Brent Royal-Gordon, we could use factory initializers with 
>> protocol extensions to return the appropriate instance conforming to a 
>> protocol for the given needs. Similar to the class cluster/abstract class 
>> method, but can work with structs too. This would be closer to the factory 
>> method pattern, since you don’t need to know exactly what type is returned, 
>> just the protocol it conforms to.
>> 
>> ## Initializing Storyboard-backed View Controller
>> This is more specific to Apple Frameworks, but having factory initializers 
>> could definitely help here. Currently, view controllers associated with a 
>> storyboard must be initialized from the client through a factory method on 
>> the storyboard instance (storyboard. 
>> instantiateViewControllerWithIdentifier()). This works when the entire flow 
>> of the app is storyboard based, but when a single storyboard is used to 
>> configure a one-off view controller, having to initialize through the 
>> storyboard is essentially use of private implementation details; it 
>> shouldn’t matter whether the VC was designed in code or storyboards, 
>> ultimately a single initializer should “do the right thing” (just as it does 
>> when using XIBs directly). A factory initializer for a View Controller 
>> subclass could handle the loading of the storyboard and returning the 
>> appropriate view controller.
>> 
>> Here are some comments from the previous thread that I believe are still 
>> relevant:
>> 
>> 
>>> On Dec 9, 2015, at 1:06 PM, Philippe Hausler <[email protected]> wrote:
>>> 
>>> I can definitely attest that in implementing Foundation we could have much 
>>> more idiomatic swift and much more similar behavior to the way Foundation 
>>> on Darwin actually works if we had factory initializers. 
>> 
>> 
>>> On Dec 7, 2015, at 5:24 PM, Brent Royal-Gordon <[email protected]> 
>>> wrote:
>>> 
>>> A `protocol init` in a protocol extension creates an initializer which is 
>>> *not* applied to types conforming to the protocol. Instead, it is actually 
>>> an initializer on the protocol itself. `self` is the protocol metatype, not 
>>> an instance of anything. The provided implementation should `return` an 
>>> instance conforming to (and implicitly casted to) the protocol. Just like 
>>> any other initializer, a `protocol init` can be failable or throwing.
>>> 
>>> Unlike other initializers, Swift usually won’t be able to tell at compile 
>>> time which concrete type will be returned by a protocol init(), reducing 
>>> opportunities to statically bind methods and perform other optimization 
>>> tricks. Frankly, though, that’s just the cost of doing business. If you 
>>> want to select a type dynamically, you’re going to lose the ability to 
>>> aggressively optimize calls to the resulting instance.
>>> 
>> 
>> 
>> I’d love to hear everyone’s thoughts on this!
>> 
>> Best,
>> Riley Testut
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to