> On Dec 18, 2015, at 8:15 AM, Thorsten Seitz <[email protected]> wrote:
> 
> Now I'm confused: I thought the idea should enable class clusters, i.e. 
> allowing AbstractBaseClass(42) to return something with the *dynamic* type of 
> ConcreteImplementation but still the static type of AbstractBaseClass.
> Otherwise I would just call ConcreteImplementation(42) if I wanted something 
> of that static type.

Got it.  If that is the case, then yes, something like a “factory init” makes 
sense to me.  It is unfortunate that such a thing would make the swift 
initializer model even MORE complex :-) but it is probably still the right way 
to go.

-Chris

> 
> -Thorsten 
> 
>> Am 18.12.2015 um 01:25 schrieb Chris Lattner via swift-evolution 
>> <[email protected]>:
>> 
>> 
>>> 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]
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected]
>> 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