[swift-evolution] [Proposal] Factory Initializers

Xiaodi Wu xiaodi.wu at gmail.com
Sun Jun 4 10:10:21 CDT 2017


No.


On Sun, Jun 4, 2017 at 10:07 Pranshu Goyal via swift-evolution <
swift-evolution at swift.org> wrote:

> Is this proposal in the pipeline for Swift 4?
>
> On 1 April 2017 at 12:03, Adrian Zubarev via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>> First, you should fix the indent in the code samples. Second, remove any
>> access modifier from inside a protocol. Third, we don’t support default
>> implementations directly inside protocols yet, so that’s a not valid
>> example.
>>
>> Now my personal concerns. As far as I can tell XIB files in an iOS
>> Project are meant for UIViewControllers in first place, but it’s a common
>> case that they are also used to create reusable UIViews. The downside of
>> that abusage is view hierarchy clustering. Most developer creating a view
>> of Self in Self, which smells to me like really bad code.
>>
>> MyCustomView // This view is useless
>>    + MyCustomView
>>        + CustomSubview1
>>    + CustomSubview1 // This is probably a dead IBOutlet
>>
>> In fact Xcode does not use the initializer from NSCoding to show a live
>> rendered view inside interface builder, instead it will call a UIViews
>> designated initializer init(frame:). That results that a lot of the
>> developer write similar code like in the following snippet:
>>
>> // This pattern results in a similar view cluster like mentioned above
>>
>> class MyCustomView : UIView {
>>     override init(frame: CGRect) {
>>         let view = loadSomehowFromNib()
>>         self.addSubview(view)
>>     }
>> }
>>
>> To solve this problem we’d need some functionality of factory
>> initializers. I believe as proposed the factory initializer won’t solve
>> that problem, because everything would be still restricted to a special
>> initializer annotated with factory.
>>
>> Personally I would want to write something like this instead.
>>
>> class MyCustomView : UIView {
>>
>>     override init(frame: CGRect) {
>>
>>         // Instantiating from a Nib file will call `init(coder:​)` on MyCustomView
>>         self = loadSomehowFromNib() // assuming () -> MyCustomView
>>
>>         //
>>         self.frame = frame
>>     }
>> }
>>
>> This should resolve the clustering issue by assigning the returned
>> instance from the function to self and create a correct view hierarchy.
>>
>> + MyCustomView
>>        + CustomSubview1
>>
>>
>>
>> --
>> Adrian Zubarev
>> Sent with Airmail
>>
>> Am 17. März 2017 um 17:26:29, Riley Testut via swift-evolution (
>> swift-evolution at swift.org) schrieb:
>>
>> Hi again everyone!
>>
>> Now that Swift 4 Stage 2 proposals are being considered, I thought it
>> might be time to revisit this proposal and see if it might align with the
>> goals set forth for Swift 4.
>>
>> As a quick tl;dr, this proposal describes a new "factory initializer"
>> that would allow you to return a value from an initializer. This would have
>> several benefits, as mentioned in the proposal itself as well as throughout
>> this mailing list. For convenience, here's a link to the proposal on
>> GitHub:
>> https://github.com/rileytestut/swift-evolution/blob/master/proposals/NNNN-factory-initializers.md
>>
>> Would love to hear any more comments on this proposal, and if we feel
>> this is appropriate for considering for Swift 4 I'll happily re-open the
>> pull request!
>>
>> Riley Testut
>>
>> On Nov 19, 2016, at 7:45 AM, arkadi daniyelian <arkdan at icloud.com> wrote:
>>
>> i would appreciate this feature.
>>
>> For unexperienced developers, its often hard to recognize *when* factory
>> is a good fit to do the job, and how exactly approach the implementation. I
>> imagine having this feature built into the language may help to choose and
>> implement factory when its the right thing to do.
>>
>> On Nov 18, 2016, at 12:23 AM, Charles Srstka via swift-evolution <
>> swift-evolution at swift.org> wrote:
>>
>>
>> Is there any chance of reviving this? It seems to me that since this
>> would require Swift initializers to be implemented internally in such a way
>> that they can return a value (as Objective-C init methods do), it may
>> affect ABI stability and thus may be germane to the current stage of Swift
>> 4 development.
>>
>>
>> Charles
>>
>>
>> On Dec 17, 2015, at 3:41 PM, Riley Testut via swift-evolution <
>> swift-evolution at swift.org> 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 <phausler at apple.com> 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 <brent at architechies.com>
>> 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
>>
>> swift-evolution at swift.org
>>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>>
>> _______________________________________________
>>
>> swift-evolution mailing list
>>
>> swift-evolution at swift.org
>>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>>
>
>
> --
> *Pranshu Goyal*
> *iOS Developer*
> *tlkn*
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170604/1b1317fb/attachment.html>


More information about the swift-evolution mailing list