Hey all! Just updated the proposal with all the recent changes, and you can check it here: https://github.com/rileytestut/swift-evolution/blob/master/proposals/NNNN-factory-initializers.md <https://github.com/rileytestut/swift-evolution/blob/master/proposals/NNNN-factory-initializers.md>
Planning on submitting the PR later tonight, so please let me know if you have any last minute feedback! Riley > On Mar 30, 2016, at 1:35 PM, Jonathan Hull <[email protected]> wrote: > > Probably ‘no' in this proposal to keep things simple. > > Long term, I would like overriding of the factory init to be the mechanism > for a post-hoc extendable factory. Disallowing it now probably makes that > easier in the future. > > Thanks, > Jon > > >> On Mar 30, 2016, at 1:20 PM, Riley Testut <[email protected] >> <mailto:[email protected]>> wrote: >> >> Another point to consider: should factory initializers be able to be >> overridden by subclasses? I vote no, just as you can't override convenience >> initializers. >> >> On Mar 30, 2016, at 3:50 AM, Jonathan Hull <[email protected] >> <mailto:[email protected]>> wrote: >> >>> Yeah. I was thinking we would want to mirror the convenience initializer >>> syntax, but I am completely ok with this as well. Honestly this is the >>> syntax I first tried to use in convenience inits while learning swift, and >>> I would love to see that migrate to something like this. My only worry >>> would be that people would be confused on when to use ClassName() and when >>> to use self.init(). Best to choose one and stick with it. >>> >>> Thanks, >>> Jon >>> >>>> On Mar 30, 2016, at 3:36 AM, Riley Testut <[email protected] >>>> <mailto:[email protected]>> wrote: >>>> >>>> If we are to enforce a different type signature for factory initializers >>>> vs required/convenience initializers (which would greatly simplify this >>>> issue), if I’m understanding correctly, there shouldn’t be a need to be >>>> able to “return” self.init(), right? Because you could do this instead: >>>> >>>> public class ConcreteBase { >>>> >>>> private init(type2: InformationToSwitchOn) { >>>> //Default implementation here >>>> } >>>> >>>> public factory init (type: InformationToSwitchOn) { >>>> if … { >>>> return SpecialSubclass(type) //Handle a special case >>>> with a more efficient implementation >>>> } >>>> return ConcreteBase(type) //Handle the general case with the >>>> main class >>>> } >>>> } >>>> >>>> class SpecialSubclass : ConcreteBase {} >>>> >>>>> On Mar 30, 2016, at 3:30 AM, Jonathan Hull <[email protected] >>>>> <mailto:[email protected]>> wrote: >>>>> >>>>> Doh! >>>>> >>>>> Sorry, typed that up in mail while working on something else at the same >>>>> time. We shouldn’t allow an init with the same signature. self.init() >>>>> could be called with different parameters. Trying to call the factory >>>>> method from the factory method should generate an error. >>>>> >>>>> We probably also want to disallow having an init with the same signature >>>>> in subclasses as well (we could pass the same info with different >>>>> parameter names) as a subclass which doesn’t override it would again be >>>>> calling the factory method. Ultimately, I would like to see the ability >>>>> to override the factory method with the behavior I described earlier… but >>>>> that is for a later proposal. >>>>> >>>>> Basically we should be able to return anything which adheres to the type, >>>>> so we are free to use other initializers on the class/subclasses. >>>>> >>>>> Thanks, >>>>> Jon >>>>> >>>>> >>>>>> On Mar 30, 2016, at 3:10 AM, Riley Testut <[email protected] >>>>>> <mailto:[email protected]>> wrote: >>>>>> >>>>>> Ah, good catch. Would that be confusing as to whether self.init() would >>>>>> lead to an infinite loop, or call the required initializer? Unlike >>>>>> convenience initializers, factory initializers might have the same >>>>>> signature as the required ones. >>>>>> >>>>>>> On Mar 30, 2016, at 2:52 AM, Jonathan Hull <[email protected] >>>>>>> <mailto:[email protected]>> wrote: >>>>>>> >>>>>>> Agreed. I would like to see what I was referring to as “stage 1” in >>>>>>> this proposal, and we can (hopefully) add on a full solution over time. >>>>>>> (I just wanted to make sure we considered those cases so we didn’t >>>>>>> block future improvements) >>>>>>> >>>>>>> Looking at the proposal, my only contention would be that we should >>>>>>> also allow self.init() to be called from the factory init (similar to a >>>>>>> convenience init). It could still be used with an AbstractBase as >>>>>>> shown in your example (especially when dealing with protocols), but it >>>>>>> shouldn’t force us to be abstract in the class case. >>>>>>> >>>>>>> In other words, we should also be able to do the following: >>>>>>> >>>>>>> public class ConcreteBase { >>>>>>> >>>>>>> private init(type: InformationToSwitchOn) { >>>>>>> //Default implementation here >>>>>>> } >>>>>>> >>>>>>> public factory init (type: InformationToSwitchOn) { >>>>>>> if … { >>>>>>> return SpecialSubclass(type) //Handle a >>>>>>> special case with a more efficient implementation >>>>>>> } >>>>>>> return self.init(type) //Handle the general case with >>>>>>> the main class >>>>>>> } >>>>>>> } >>>>>>> >>>>>>> class SpecialSubclass : ConcreteBase {} >>>>>>> >>>>>>> >>>>>>> >>>>>>> The behavior should simply be that we can return any init’d object that >>>>>>> conforms to the given type. >>>>>>> >>>>>>> Thanks, >>>>>>> Jon >>>>>>> >>>>>>> >>>>>>>> On Mar 30, 2016, at 2:20 AM, Riley Testut <[email protected] >>>>>>>> <mailto:[email protected]>> wrote: >>>>>>>> >>>>>>>> Ultimately, while these are good points, I feel the full mechanism for >>>>>>>> class clusters belong in a separate proposal. The focus for this one I >>>>>>>> believe should be the underlying mechanism of factory initializers; >>>>>>>> should that be approved, then we can focus on adding additional >>>>>>>> features on top of it. >>>>>>>> >>>>>>>> That being said, I’ve written up essentially a final version of the >>>>>>>> proposal, which you can find here: >>>>>>>> https://github.com/rileytestut/swift-evolution/blob/master/proposals/NNNN-factory-initializers.md >>>>>>>> >>>>>>>> <https://github.com/rileytestut/swift-evolution/blob/master/proposals/NNNN-factory-initializers.md>. >>>>>>>> Assuming everyone is happy with it, I’ll send a pull request in the >>>>>>>> next few days to the main-repo. But please, give any last minute >>>>>>>> feedback now! >>>>>>>> >>>>>>>>> On Mar 24, 2016, at 5:12 PM, Jonathan Hull <[email protected] >>>>>>>>> <mailto:[email protected]>> wrote: >>>>>>>>> >>>>>>>>> Comments inline. >>>>>>>>> >>>>>>>>>> On Mar 24, 2016, at 12:10 AM, Riley Testut <[email protected] >>>>>>>>>> <mailto:[email protected]>> wrote: >>>>>>>>>> >>>>>>>>>> While I do believe your proposed additions have their benefits, my >>>>>>>>>> gut tells me this is too large a change to Swift for an arguably >>>>>>>>>> small gain. For this proposal, I'm wanting to keep the change as >>>>>>>>>> minimalistic as possible, while still providing enough flexibility >>>>>>>>>> and use cases to warrant it. >>>>>>>>> >>>>>>>>> I can definitely see the argument that extensibility is out of scope >>>>>>>>> for Swift 3, but I do want to make sure that it is possible for us to >>>>>>>>> have extensibility in the future (that we don’t block ourselves from >>>>>>>>> doing it). >>>>>>>>> >>>>>>>>> I strongly disagree that the gain is small. One of the core benefits >>>>>>>>> of both Swift/ObjC (and now POP) is the ability to extend things >>>>>>>>> post-hoc, without access to the original code. >>>>>>>>> >>>>>>>>> I often write libraries & SDKs, so the users of my code don't have >>>>>>>>> access to the original code. I guess extensibility is less necessary >>>>>>>>> when you control the entire codebase, but you still have to refactor >>>>>>>>> your factory whenever you subclass (or adhere to a protocol), which I >>>>>>>>> find problematic. >>>>>>>>> >>>>>>>>> This is something I run into a lot while writing actual code, so it >>>>>>>>> isn’t just a theoretical concern. >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>>> Interesting you bring up the registering of subclasses, as that is >>>>>>>>>> similar to the very original proposal, and actually similar to what >>>>>>>>>> I'm doing in my own app. Effectively, I have an Objective-C base >>>>>>>>>> class, and in +load it dynamically finds all subclasses using the >>>>>>>>>> Objective-C runtime, and stores a reference to them. Then in the >>>>>>>>>> initializer, it returns the appropriate subclass based on the >>>>>>>>>> initialization parameters. This was my solution to the superclass >>>>>>>>>> not having to explicitly know each individual subclass. >>>>>>>>>> >>>>>>>>>> Using factory initializers, however, this pattern could be used in >>>>>>>>>> pure Swift, albeit with some minor modifications. At program start, >>>>>>>>>> the program could register subclasses with the superclass, and then >>>>>>>>>> in the initializer would simply return the appropriate subclass >>>>>>>>>> (similar to NSURLProtocol, I believe). >>>>>>>>> >>>>>>>>> Yes, I have also used load in this way in ObjC. In Swift, I think >>>>>>>>> the compiler could easily build an array/table of the overloads of >>>>>>>>> factory inits. This avoids having to register explicitly (the >>>>>>>>> declaration itself implies intent to register), and doesn’t take up >>>>>>>>> any cycles during execution. >>>>>>>>> >>>>>>>>> I ran into the problem of when to register the other day in a current >>>>>>>>> project, as Swift doesn’t have an equivalent to +load that I am aware >>>>>>>>> of. I had to settle for something of a hack which gets called on >>>>>>>>> first use… but it was only a partial solution which worked in that >>>>>>>>> particular case. How do the swift classes/enums/structs get called >>>>>>>>> to register themselves? >>>>>>>>> >>>>>>>>> We may want to propose adding a +load equivalent for Swift types, >>>>>>>>> since it does come up occasionally. It is one of those things which >>>>>>>>> you don’t need often, but when you do, you really need it. >>>>>>>>> Ironically, this was one of the uses of the original feature I talked >>>>>>>>> about earlier (we used it to provide the equivalent of +load, >>>>>>>>> awakeFromNib, etc… in the language). >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>>> As for rationale for protocol (factory) initializers, a common >>>>>>>>>> pattern I've come across when developing my internal frameworks is >>>>>>>>>> to design a protocol, and then to provide a default implementation >>>>>>>>>> of the protocol with a type (typically a struct). I feel this >>>>>>>>>> relationship could be bridged easier by simply returning this type >>>>>>>>>> from a protocol initializer, which could even potentially allow me >>>>>>>>>> to declare the actual type as private, so for all intents and >>>>>>>>>> purposes the client does simply get an initialized protocol object >>>>>>>>>> (similar in part to creating an anonymous class conforming to a >>>>>>>>>> protocol in Java). >>>>>>>>> >>>>>>>>> I strongly agree that we should have factory initializers for >>>>>>>>> protocols for the reasons you state here, plus many others. It just >>>>>>>>> seems like a natural fit. >>>>>>>>> >>>>>>>>> >>>>>>>>> I would like to see a 3 stage approach: >>>>>>>>> >>>>>>>>> Stage 1: Declaring an init as “factory” allows you to return any >>>>>>>>> fully inited object which fits the type (including calling self.init >>>>>>>>> like a convenience init would and then returning it). If the init is >>>>>>>>> failable, you can also return nil. This works both on classes and >>>>>>>>> protocols. >>>>>>>>> >>>>>>>>> Stage 2: The compiler builds a table of the overrides of a given >>>>>>>>> factory init, and there is some syntax to call them (e.g. “let sub = >>>>>>>>> subclasses.init(value)”) such that the first one to return non-nil is >>>>>>>>> the return value to that call. Thorsten’s depth first + alphabetical >>>>>>>>> ordering would be adequate to make the behavior predictable. Again, >>>>>>>>> this should work for both classes and protocols. (I am open to better >>>>>>>>> ideas for syntax/naming) >>>>>>>>> >>>>>>>>> Stage 3: We allow greater control over the ordering in the table. >>>>>>>>> This still needs thought both on syntax and method. Something >>>>>>>>> similar to operator precedence (or autolayout priority) would work in >>>>>>>>> a pinch, but isn’t super elegant. In practice, it might be enough >>>>>>>>> just to be able to declare that something needs to be before/after a >>>>>>>>> specific subclass in the list. >>>>>>>>> >>>>>>>>> >>>>>>>>> Note: A slightly different approach to stage 2 (for classes) might >>>>>>>>> have only the direct subclasses in the table, and then the subclasses >>>>>>>>> have the option to call off to their own subclasses in the same >>>>>>>>> manner if desired. This has the tradeoff that each level needs to >>>>>>>>> plan for extensibility (i.e. you can’t override something which >>>>>>>>> wasn’t expecting to be subclassed), but I do like how it simplifies >>>>>>>>> the model a bit. >>>>>>>>> >>>>>>>>> I have a feeling that the proper syntax for stages 2/3 may become >>>>>>>>> more obvious once the design work around mixins/protocols+storage >>>>>>>>> gets done. It may just fall out of the disambiguation syntax... >>>>>>>>> >>>>>>>>> Thanks, >>>>>>>>> Jon >>>>>>>>> >>>>>>>>>> On Mar 22, 2016, at 5:21 PM, Jonathan Hull <[email protected] >>>>>>>>>> <mailto:[email protected]>> wrote: >>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Yes and No. >>>>>>>>>>> Yes, because this is a problem I run into all the time, and I >>>>>>>>>>> really want swift to have a solution for it. I especially like >>>>>>>>>>> Brent’s idea of a protocol init. >>>>>>>>>>> No, because I have gotten a bit greedy. I want us to take a step >>>>>>>>>>> back and look at the underlying problem to see if we can come up >>>>>>>>>>> with something which completely solves it… and I think factories >>>>>>>>>>> get us only part way there. Let’s take a moment and see if we can >>>>>>>>>>> create something uniquely swift before we copy/paste existing >>>>>>>>>>> solutions. >>>>>>>>>>> Think about Cocoa’s class clusters for a moment. I love them, but >>>>>>>>>>> they are a pain to subclass. To the level where any beginning Cocoa >>>>>>>>>>> instruction tells you explicitly not to subclass them. Similarly, >>>>>>>>>>> even in my own factories, they are always a pain to extend. >>>>>>>>>>> I want our factory inits to be extensible by default. >>>>>>>>>>> >>>>>>>>>>> By extensible, I mean that I want to be able to add a new subclass >>>>>>>>>>> (or a new entity satisfying a protocol), and have it come out of >>>>>>>>>>> the factory when appropriate without editing the base class! >>>>>>>>>>> Madness, I know, but: >>>>>>>>>>> 1) I may not have access to the source of the base class (e.g. >>>>>>>>>>> Cocoa Collections) >>>>>>>>>>> 2) I always feel a bit dirty giving the base class knowledge of >>>>>>>>>>> it’s subclasses >>>>>>>>>>> 3) It is a royal pain, and a potential source of errors as things >>>>>>>>>>> get refactored when adding new subclasses >>>>>>>>>>> >>>>>>>>>>> I think I have at least the seed of an idea of how to solve this, >>>>>>>>>>> and I am hoping that one of you (who are all much smarter than I) >>>>>>>>>>> might have the key to getting it the rest of the way. >>>>>>>>>>> I ran into this problem again last week, and it made me think of an >>>>>>>>>>> old language I used to use... >>>>>>>>>>> There was a small programming language I used to use in the 90’s >>>>>>>>>>> which had an interesting core language feature we called >>>>>>>>>>> “handlers”. These were a lot like registering for notifications, >>>>>>>>>>> except that writing a function (with a special “Handler” attribute: >>>>>>>>>>> “Handler func myFuncName()") was all you needed to do to register. >>>>>>>>>>> Writing “Handle myFuncName()” would then systematically call every >>>>>>>>>>> function with that name and the Handler attribute. >>>>>>>>>>> That is, instead of calling a single function, it would >>>>>>>>>>> systematically call a series of functions (all with the same name). >>>>>>>>>>> There was one other thing that made these handlers special. Each >>>>>>>>>>> one had the option, when it was called, to reply that it was the >>>>>>>>>>> one true handler, and the others didn’t need to be called. >>>>>>>>>>> Basically, it said “I've got this!”. This even allowed it to return >>>>>>>>>>> a result to the caller. >>>>>>>>>>> The original intent of this feature (and why it was a core language >>>>>>>>>>> feature) was to handle events. It would handle things like hit >>>>>>>>>>> testing and key events fairly elegantly. It was a powerful feature, >>>>>>>>>>> so it was quickly used for other things. It made things like >>>>>>>>>>> plug-ins ridiculously simple. We even used it for a form of error >>>>>>>>>>> handling. >>>>>>>>>>> I remember helping to write a page layout program in it, and we >>>>>>>>>>> used handlers not just for the hit testing, but for the tool >>>>>>>>>>> palette as well. The end result was that you were able to add new >>>>>>>>>>> shapes and new tools without modifying existing code at all. It is >>>>>>>>>>> a feature I miss all the time... >>>>>>>>>>> >>>>>>>>>>> That is more power than we need here, but it provided me the >>>>>>>>>>> inspiration for a potential solution to the factory problem. Back >>>>>>>>>>> to swift… >>>>>>>>>>> >>>>>>>>>>> The idea here is to give each interested subclass a chance to say >>>>>>>>>>> “I've got this!”. The factory init runs through each of the >>>>>>>>>>> subclasses’ overrides until it finds one that doesn’t return nil. >>>>>>>>>>> New subclasses can be added and they will be given a chance as well >>>>>>>>>>> (without modifying the base class). The first subclass to >>>>>>>>>>> successfully init wins. (only subclasses which override the factory >>>>>>>>>>> init would be considered) >>>>>>>>>>> >>>>>>>>>>> class AbstractBase { >>>>>>>>>>> public factory init?(type: InformationToSwitchOn){ >>>>>>>>>>> //I like having an explicit call, so that the traditional >>>>>>>>>>> (non-distributed) factory is possible as well >>>>>>>>>>> return factory.init(type) //We could also call this >>>>>>>>>>> “subclass.init(type)” to mirror super >>>>>>>>>>> } >>>>>>>>>>> } >>>>>>>>>>> class ConcreteImplementation : AbstractBase { >>>>>>>>>>> public factory override init?(type: InformationToSwitchOn){ >>>>>>>>>>> guard type == compatibleWithThisType else {return nil} //If >>>>>>>>>>> info doesn’t work for us, we return nil, and the next class gets a >>>>>>>>>>> shot >>>>>>>>>>> //Init concrete type here >>>>>>>>>>> } >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> The main issue which still needs to be solved is that the order >>>>>>>>>>> they get called sometimes really matters (this was solved by a well >>>>>>>>>>> defined ordering + IDE features in the language mentioned above). >>>>>>>>>>> For the most part, as long as subclasses are called before their >>>>>>>>>>> superclasses (or there is a some method for cascading), it works. >>>>>>>>>>> There are still times where you want to define a specific ordering >>>>>>>>>>> though (e.g. a new subclass wants to get called before an existing >>>>>>>>>>> subclasses to override some of it’s use cases). >>>>>>>>>>> I see a few options (and I would love to hear more): >>>>>>>>>>> - subclasses define a numeric precedence (similar to operators >>>>>>>>>>> now). This is probably the most effective stop-gap solution, but is >>>>>>>>>>> not elegant. >>>>>>>>>>> - subclasses do whatever we change operator precedence to do in the >>>>>>>>>>> future >>>>>>>>>>> - optionally allow subclasses to name another specific subclass >>>>>>>>>>> that they are before/after >>>>>>>>>>> - allow subclasses to declare that they would like to be earlier or >>>>>>>>>>> later (or that they don’t care) in the calling list. subclasses >>>>>>>>>>> defined outside of the module where the base class was defined >>>>>>>>>>> would be placed more extremely early/late. Exact order is >>>>>>>>>>> undefined, but rough ordering is possible. >>>>>>>>>>> - return (to the superclass) an array of all subclasses which >>>>>>>>>>> successfully inited. It can then select which one it wants and >>>>>>>>>>> return it. This seems overly inefficient to me, since you are >>>>>>>>>>> initializing a bunch of unused objects. >>>>>>>>>>> - <Your idea here> >>>>>>>>>>> >>>>>>>>>>> The end result is that you can extend factories of both classes and >>>>>>>>>>> protocols without access to the original source code. >>>>>>>>>>> >>>>>>>>>>> I also don’t think that the base should always need to be abstract. >>>>>>>>>>> Factory inits should allow returning subclasses as a way of >>>>>>>>>>> replacing themselves with a subclass, and returning nil if they are >>>>>>>>>>> failable, but if there is no return (or return self), it can create >>>>>>>>>>> an instance of itself. This way, it provides a customization point >>>>>>>>>>> where subclasses can handle special cases, but the class itself >>>>>>>>>>> provides an obvious default (i.e. a much less messy form of class >>>>>>>>>>> cluster). >>>>>>>>>>> >>>>>>>>>>> class Base { >>>>>>>>>>> public factory init(type: InformationToSwitchOn){ >>>>>>>>>>> if let subclass = factory.init(type){ >>>>>>>>>>> return subclass >>>>>>>>>>> } >>>>>>>>>>> return self.init()//If subclasses didn’t work, initialize >>>>>>>>>>> ourselves >>>>>>>>>>> } >>>>>>>>>>> } >>>>>>>>>>> >>>>>>>>>>> Thoughts? Too crazy to consider? >>>>>>>>>>> >>>>>>>>>>> Thanks, >>>>>>>>>>> Jon >>>>>>>>>>> >>>>>>>>>>> On Feb 8, 2016, at 11:26 AM, Charles Srstka <cocoadev at >>>>>>>>>>> charlessoft.com >>>>>>>>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>> wrote: >>>>>>>>>>> >>>>>>>>>>> >> On Dec 17, 2015, at 3:41 PM, Riley Testut via swift-evolution >>>>>>>>>>> >> <swift-evolution at swift.org >>>>>>>>>>> >> <https://lists.swift.org/mailman/listinfo/swift-evolution>> >>>>>>>>>>> >> 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 >>>>>>>>>>> >>> <https://lists.swift.org/mailman/listinfo/swift-evolution>> >>>>>>>>>>> >>> 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 >>>>>>>>>>> >>> <https://lists.swift.org/mailman/listinfo/swift-evolution>> >>>>>>>>>>> >>> 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> >>>>>>>>>>> >> https://lists.swift.org/mailman/listinfo/swift-evolution >>>>>>>>>>> >> <https://lists.swift.org/mailman/listinfo/swift-evolution> >>>>>>>>>>> > >>>>>>>>>>> > Was any proposal for this ever written up? It would be really >>>>>>>>>>> > useful to have, and it appeared to have the support of several >>>>>>>>>>> > Apple staff members. >>>>>>>>>>> > >>>>>>>>>>> > Charles >>>>>>>>>>> >>>>>>>>> >>>>>>>> >>>>>>> >>>>>> >>>>> >>>> >>> >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
