I thought this already went in review somehow, sorry a +1 from me as well. [[iOS messageWithData:ideas] broadcast]
> On 10 Apr 2016, at 19:14, Radosław Pietruszewski via swift-evolution > <swift-evolution@swift.org> wrote: > > Nice! > > I must admit, my first reaction to this proposal was “uhhh, why complicate > initializers even more?”. But then I hit these two roadblocks: > > 1. I wanted to add an initializer on `NSTimer` extension that returns the > (toll-free-bridged) value from CFRunLoopTimerCreateWithHandler. Sadly, this > is impossible, and so I have to write NSTimer.new(…) :( > 2. I wanted to add a custom initializer to a class inheriting from UIButton. > But I can’t, because the initializer for UIButton is `convenience init(type > buttonType: UIButtonType)` :( > > A `factory init` allowing me to use both the initializer syntax and return an > object from some other initializer would solve both problems. The > "Initializing Storyboard-backed View Controller” use case is also compelling > to me. > > +1. > > — Radek > >> On 09 Apr 2016, at 21:17, Riley Testut via swift-evolution >> <swift-evolution@swift.org> wrote: >> >> Hello again everyone! >> >> Just an update, I did submit the PR about a week ago, and you can check it >> out here: >> https://github.com/apple/swift-evolution/pull/247 >> >> As far as I know, now we wait until a core team member reviews the PR, and >> either suggests changes, or accepts it and initiates a review. Of course, if >> this is incorrect, please let me know so I can do whatever next steps there >> are :-) >> >> Thanks again for all the contributions to this proposal, hope we see it get >> approved soon! >> Riley >> >>> On Apr 4, 2016, at 11:58 AM, Riley Testut <rileytes...@gmail.com> wrote: >>> >>> 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 >>> >>> 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 <jh...@gbis.com> 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 <rileytes...@gmail.com> 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 <jh...@gbis.com> 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 <rileytes...@gmail.com> 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 <jh...@gbis.com> 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 <rileytes...@gmail.com> >>>>>>>>> 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 <jh...@gbis.com> 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 <rileytes...@gmail.com> >>>>>>>>>>> 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. >>>>>>>>>>> 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 <jh...@gbis.com> wrote: >>>>>>>>>>>> >>>>>>>>>>>> Comments inline. >>>>>>>>>>>> >>>>>>>>>>>>> On Mar 24, 2016, at 12:10 AM, Riley Testut >>>>>>>>>>>>> <rileytes...@gmail.com> 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 <jh...@gbis.com> >>>>>>>>>>>>>> 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> wrote: >>>>>>>>>>>>>> >>>>>>>>>>>>>> >> 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 >>>>>>>>>>>>>> > >>>>>>>>>>>>>> > 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 >> swift-evolution@swift.org >> https://lists.swift.org/mailman/listinfo/swift-evolution > > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution