Strong +1 on this, particularly on the part about protocol initializers. This would bring together some of the best aspects of both Objective-C class clusters and Swift protocol-oriented programming and would be a huge benefit to application developers.
Charles > On Dec 17, 2015, at 3: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 { > > } > > 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
